前端解决跨域的几种方式

前言

前端开发过程中,跨域是不可避免会出现的问题,一般我们使用代理的比较多,实际上不止有代理能够解决,还有更为常见的 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,
      },
    },
  },
相关推荐
@PHARAOH3 分钟前
WHAT - 前端开发流程 SOP(标准操作流程)参考
前端·领导力
松树戈1 小时前
plus-ui&RuoYi-Vue-Plus 基于pgSql本地运行实践
前端·vue.js·spring boot·ui
new6669991 小时前
css画图形
前端·css
Yvonne爱编码2 小时前
CSS- 1.1 css选择器
前端·css·状态模式·html5·hbuilder
山河故人1632 小时前
uniapp使用npm下载
前端·npm·uni-app
-曾牛2 小时前
基于微信小程序的在线聊天功能实现:WebSocket通信实战
前端·后端·websocket·网络协议·微信小程序·小程序·notepad++
一口一个橘子3 小时前
[ctfshow web入门] web72
前端·web安全·网络安全
Web极客码3 小时前
如何使用WordPress SEO检查器进行实时内容分析
前端·seo·wordpress
Stella25213 小时前
【Vue】CSS3实现关键帧动画
前端·vue.js·css3
junjun.chen06063 小时前
【在qiankun模式下el-dropdown点击,浏览器报Failed to execute ‘getComputedStyle‘ on ‘Window‘: parameter 1 is not o
前端·javascript·前端框架