手把手带你实践4种前端跨域方式(附源码)

本文最后更新于:8 个月前

四种常用跨域方式:Vite配置代理跨域、手动配置CORS、使用cors库、Nginx配置代理

手把手带你实践4种前端跨域方式(附源码)

一、实验环境

前端项目:使用Vite创建一个Vue项目

后端项目:使用Express搭建一个web服务器

硬件:本地计算机(需要安装node.js环境,且需要符合vite对node的版本需求) + 阿里云轻量服务器(非必须)

二、准备工作

分别使用ViteExpress创建前端、后端项目。具体过程不展开赘述,直接放源码:

Qiuzcc/CORS_expriment: 用于探究前后端常用跨域方式的demo(github.com)

(大家可以clone下来直接用,具体的使用方法已经在代码注释和readme中进行了详细说明)

三、实验内容

1. 实验一:不进行任何配置

先后启动后端、前端项目,打开浏览器,查看控制台,观察到:XHR请求被CORS策略阻拦了

image-20230419205017152

解析:

  • 网页的源为:http://localhost:5173:,服务器的源为:http://localhost:3000两者都端口不一致,导致不同源

  • 从后端的access监听日志看,服务器已经做出了响应,并且实际上将Get请求的响应发回给了浏览器(如下图)。而 POST 和 PUT 请求则先发送了 OPTIONS 预检请求,在没有收到服务端返回的 CORS 同意字段之后,浏览器拒绝发送 POST 和 PUT 请求。

    (「简单请求」直接发送实际请求,「非简单请求」先发送预检请求,再根据预检结果决定是否发送实际请求。更多详细内容,请阅读:一文说清CORS - timegogo

    image-20230419205058520
  • 从浏览器的「开发者工具」-「网络」中可以看到,“无法加载响应数据”,所以实际上是浏览器拒绝了解析响应(如下图一),POST 和 PUT 请求 没有发送出去(如下图二)

    image-20230419205320636

    image-20230419205415026

2. 实验二:在vite开发模式下配置代理跨域

配置参考链接:开发服务器选项 | Vite 官方中文文档 (vitejs.dev)

vite.config,js中配置server.proxy,如下:

image-20230413211729118

需要注意的是:这时在发送XHR请求时,url也需要相应地改变

image-20230413212138237

查看【网络请求】,GET, POST, PUT三个请求都成功发送了,但是可以看到请求的 url 并不是服务端的地址,而是http://localhost:5173/api/。所以,实际上,AxiosInstance 是向 dev server 发送的请求

image-20230419212542893

image-20230419212620330

原理解析:

这种方式能够解决跨域问题的原理是:

  • AxiosInstance将请求发送给dev serverdev server再向真正的target发送请求,因为dev server不是浏览器,所以不受同源策略限制
  • dev server获得来自target的响应后,返回给AxiosInstance,因为dev serverinstance是同源的,所以可以被解析

注意:

  • 这种方式只能在开发模式下使用!(因为生产环境下已经没有dev server这个东西了)

使用Tips:

  • 可以通过 Axios 的 baseUrl 统一设置代理路径头,比如上面的/api,这样切换到生产环境时,可以快速切换url

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // env.development
    BASE_URL = '/api'

    //env.production
    BASE_URL = 'http://127.0.0.1:3000'

    // .js文件
    const instance = axios.create({
    baseUrl: import.meta.env.BASE_URL
    })

    instance.get('/data').then().catch()
    // 开发环境下为/api/data,然后通过dev server代理转发
    // 生产环境下为http://127.0.0.1:3000/data

3. 实验三:后端手动配置CORS

CORS,全称是“跨域资源共享”(Cross-origin resource sharing)。是一个W3C标准。它新增了一组HTTP标头字段,来允许服务器声明哪些源站通过浏览器有权限访问哪些资源。

第一步,在后端配置CORS

image-20230413222957779

第二步,前端正常发送XHR请求即可

image-20230413223053600

查看【网络请求】

  • GET请求获得了CORS同意字段(Access-Control-Allow-Origin等)
  • PUT和GET 都先发送了 OPTIONS 预检请求,收到CORS同意字段后,发送了实际的PUT和POST请求

image-20230419213311647

image-20230419213447613

原理解析:

首先,浏览器能够自动识别请求是否同源。然后,对于非同源请求,浏览器根据服务端返回的响应头相关字段(Access-Control-Allow-Origin等)决定是否同意该跨域请求正常进行。例如:比对Access-Control-Allow-Origin字段与请求的Origin字段是否相同(相同则加载响应,不相同则阻止加载)

image-20230413224353112

使用Tips:动态允许多个源

1
2
3
4
5
6
7
8
app.use('*',(req,res,next)=>{
//匹配多个<origin>源
const corsFilter = ["https://timegogo.top", 'http://localhost:5173']
const origin = req.get('Origin')
const allowOrigin = corsFilter.includes(origin) ? origin : corsFilter[0]
res.header("Access-Control-Allow-Origin", allowOrigin);
next()
})

4. 实验四:使用cors库实现跨域

第一步,在后端安装cors - npm (npmjs.com)

1
npm i cors

第二步,在后端进行配置

image-20230413230146664

第三步,在前端正常发送请求即可

结果与【实验三:后端手动配置CORS】一致

原理解析:

与实验三手动配置CORS原理相同,只是在这里 cors 库 把CORS的配置 集成封装起来了。相比起手动配置CORS,使用这种方式更加简单高效,而且不容易出现错误,推荐使用。

5. 实验五:配置代理服务器

在生产环境下,不存在dev server,但是可以通过Nginx、Apache等作为代理服务器。

接下来的操作,需要将代码打包上传到云服务器


手把手带你实践4种前端跨域方式(附源码)
http://timegogo.top/2023/04/13/前端工程化/安全:跨域实验探究/
作者
丘智聪
发布于
2023年4月13日
更新于
2023年7月16日
许可协议