前端解决跨域的几种方式

前言

前端开发过程中,跨域是不可避免会出现的问题,一般我们使用代理的比较多,实际上不止有代理能够解决,还有更为常见的 cros 方案,并且这里也会简单介绍跨域的特征,以及从哪里解决入手解决问题的

跨域与策略

跨域问题就是前端服务与后端服务部署的域名不一致,用户使用浏览器下载前端代码时了解到了前端服务地址,在网络请求访问服务端地址时,发现访问服务端域名与前端的域名不一致,此时会自动在请求头中添加 Origin 字段,服务器发现不是同源,则默认直接拒绝访问,引出出现了跨域

这里解释一下跨域:域名不一样即为跨域

https://www.baidu.com 为例

  • http://www.baidu.com :跨域, 协议不同(一个https,一个http)
  • https://www.taobao.com: 跨域,主域名不同
  • https://tieba.baidu.com: 跨域,子域名不同(一般的通配符证书指的是多个子域名)
  • https://www.baidu.com:3000:跨域,端口号不同
  • https://www.baidu.com/home.html: 不跨域,同源,可以理解为同一个项目不同路径下的子页面

跨域解决方案思路

  • 通过浏览器的特性,绕开添加 origin 字段的方式,这样后端没办法识别是否跨域(使用 postman 的时候碰不到就是这个原因),但使用浏览器加载的前端页面就没办法主动绕开了,但是有个漏洞就是 JSONP 方案,不安全,且仅支持get方法,因此也不推荐
  • 服务端就是收到了 origin 不一致的情况,仍然允许请求,这就是 CROS 方案
  • 设置代理,将前端与代理服务部署到同一个域名下,前端通过代理(中间人)访问后端,也就是前端的请求,代理会转发给后端,可以认为浏览器将代理当成了后端,因此认为同源,则避免了此类问题

目前比较常用的几种跨域解决方案

  • 前后端放置到一个域名下,但是实际开发过程中很不实际(一些大厂可以忽略,甚至一些大厂也不是所有部门都这么做)
  • 后端设置允许跨域,即不采用同源策略,或者设置白名单(实际就是 CROS 方案)
  • 部署后设置 Nginx 代理,或前端直接设置代理,将前端服务与代理服务运行到统一域名下,即使用中间服务器代理前端访问接口:前端 <=> 代理服务器 <=> 后端

JSONP(不推荐)

JSONP 的核心原理是利用了 <script> 标签的 src 属性不受同源策略限制的特点。

通过在页面中动态创建 <script> 标签,向服务器请求一个 JSON 数据,并在请求的 URL 中添加一个回调函数名作为参数。

服务器收到请求后,会将 JSON 数据包装在这个回调函数中返回给客户端。

客户端的 <script> 标签会执行这个返回的 JavaScript 代码,从而调用回调函数并将 JSON 数据作为参数传入,实现数据的跨域获取。

js 复制代码
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
  </head>

  <body>
    <script>
      function handleResponse(data) {
        console.log('Received data:', data)
      }

      const script = document.createElement('script')
      script.src = 'http://www.baidu.com?callback=handleResponse'
      document.body.appendChild(script)
    </script>
  </body>
</html>

//服务端response需要拼接成函数脚本,便于客户端执行
const response = `${callback}(${JSON.stringify(data)})`;
res.setHeader('Content-Type', 'application/javascript');
res.send(response);

CORS(Cross-Origin Resource Sharing)

CORS 是一种现代的跨域解决方案,它通过服务器设置响应头来允许跨域请求。当浏览器检测到请求是跨域的,会自动在请求头中添加 Origin 字段,服务器根据这个字段来判断是否允许该请求

js 复制代码
//后端设置允许所有源即可
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

//或者像我前面设置的nestjs项目似的允许跨域
app.enableCors()

代理

在开发环境中,可以使用代理服务器来解决跨域问题

代理服务器与前端代码运行在同一域名下,前端将请求发送给代理服务器,代理服务器再将请求转发到目标服务器,并将响应返回给前端

下面是常见的 http-proxy-middleware中间件、nextjs代理、vite代理

js 复制代码
//setupProxy.js

// 配置代理中间件,以进行连接、表达、浏览器同步等。
const { createProxyMiddleware } = require("http-proxy-middleware");

// 配置代理服务
const apiProxy = createProxyMiddleware("/api", {
    target: 'http://172.27.106.56:5000/',
    ws: true,
    // changeOrigin: true,
    // pathRewrite: { '^': '' },
});

module.exports = function (app) {
    app.use(apiProxy);
}

next.config.mjs

js 复制代码
//next.config.mjs
rewrites() {
    return [
        // 当请求路径符合 /api 时,将请求转发到代理服务器
        {
            source: '/api/:path*',
            destination: 'http://192.168.1.1:4000/api/:path*',
        },
    ];
},

vite.config.ts

js 复制代码
server: {
    //代理
    proxy: {
      '/api': {
        // 这里填写后端地址
        target: 'http://192.168.1.1:4000', //测试服务
        changeOrigin: true,
      },
    },
  },
相关推荐
Fantasywt3 小时前
THREEJS 片元着色器实现更自然的呼吸灯效果
前端·javascript·着色器
IT、木易4 小时前
大白话JavaScript实现一个函数,将字符串中的每个单词首字母大写。
开发语言·前端·javascript·ecmascript
张拭心6 小时前
2024 总结,我的停滞与觉醒
android·前端
念九_ysl6 小时前
深入解析Vue3单文件组件:原理、场景与实战
前端·javascript·vue.js
Jenna的海糖6 小时前
vue3如何配置环境和打包
前端·javascript·vue.js
星之卡比*7 小时前
前端知识点---库和包的概念
前端·harmonyos·鸿蒙
灵感__idea7 小时前
Vuejs技术内幕:数据响应式之3.x版
前端·vue.js·源码阅读
烛阴7 小时前
JavaScript 构造器进阶:掌握 “new” 的底层原理,写出更优雅的代码!
前端·javascript
Alan-Xia7 小时前
使用jest测试用例之入门篇
前端·javascript·学习·测试用例
浪遏7 小时前
面试官😏 :文本太长,超出部分用省略号 ,怎么搞?我:🤡
前端·面试