前端解决跨域的几种方式

前言

前端开发过程中,跨域是不可避免会出现的问题,一般我们使用代理的比较多,实际上不止有代理能够解决,还有更为常见的 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,
      },
    },
  },
相关推荐
Larcher4 小时前
新手也能学会,100行代码玩AI LOGO
前端·llm·html
徐子颐4 小时前
从 Vibe Coding 到 Agent Coding:Cursor 2.0 开启下一代 AI 开发范式
前端
小月鸭4 小时前
如何理解HTML语义化
前端·html
jump6805 小时前
url输入到网页展示会发生什么?
前端
诸葛韩信5 小时前
我们需要了解的Web Workers
前端
brzhang5 小时前
我觉得可以试试 TOON —— 一个为 LLM 而生的极致压缩数据格式
前端·后端·架构
yivifu5 小时前
JavaScript Selection API详解
java·前端·javascript
这儿有一堆花5 小时前
告别 Class 组件:拥抱 React Hooks 带来的函数式新范式
前端·javascript·react.js
十二春秋5 小时前
场景模拟:基础路由配置
前端
六月的可乐5 小时前
实战干货-Vue实现AI聊天助手全流程解析
前端·vue.js·ai编程