跨域常见的解决方法

之前有被人问到过跨域这块的东西,当时答得有点模糊,再回顾一下

>

跨域概念

浏览器中有一个安全策略叫同源策略,意思是协议、主机、端口必须相同,如果其一不同,则称之为跨域,对于跨域的请求,出于安全考虑,浏览器会对其访问进行一些限制

Ajax

对于传统ajax,浏览器默认不允许其发送跨域请求,但是有三种方案可以解决

  1. 代理

代理适用的场景是:生产环境不发生跨域,但开发环境发生跨域
比较常见的是通过webpack集成的 devServer 实现代理去解决跨域问题

1
2
3
4
5
6
7
8
9
10
11
// vue 的开发服务器代理配置
// vue.config.js
module.exports = {
devServer: { // 配置开发服务器
proxy: { // 配置代理
"/api": { // 若请求路径以 /api 开头
target: "http://dev.taobao.com", // 将其转发到 http://dev.taobao.com
},
},
},
};
  1. JSONP

通过前后端配合,利用 script 标签不受同源策略限制去令服务端响应一段JS代码,将需要返回的数据作为参数传入该代码中,客户端再负责调用,类似ajax的回调函数。

但JSONP有一个明显的问题就是只能发送Get请求

  1. CORS

CORS是基于http1.1的一种跨域解决方案。全称叫跨域资源共享
总体思路是:如果浏览器要跨域访问服务器的资源,需要获得服务器的允许
针对不同的请求,CORS 规定了三种不同的交互模式,分别是:简单请求需要预检的请求附带身份凭证的请求

当请求方法属于get、post、head;请求头仅包含安全的字段;请求头如果包含Content-Type,仅限 text/plainmultipart/form-dataapplication/x-www-form-urlencoded同时满足上面三个条件后则判断为简单请求。

常见的安全字段如下:

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type
  • DPR
  • Downlink
  • Save-Data
  • Viewport-Width
  • Width

当浏览器判断某个请求为简单请求后,会在请求头中自动添加 Origin 字段,用以告诉服务器,是哪个源地址在跨域请求,服务器在收到请求后,需要添加 Access-Control-Allow-Origin 用以表示开放的权限(* 表示允许所有,也可以写具体的地址表示只允许该源下的请求访问)

对于需要预检的请求(不符合上述条件),浏览器会先发送预检请求,如果服务器允许访问,则浏览器发送真实请求,最后服务器完成真实请求的响应

预检请求有以下特征:

  • 请求方法为OPTIONS
  • 没有请求体
  • 请求头中包含
    • Origin:请求的源,和简单请求的含义一致
    • Access-Control-Request-Method:后续的真实请求将使用的请求方法
    • Access-Control-Request-Headers:后续的真实请求会改动的请求头

对于预检请求的响应,不需要请求体,只需要在响应头中添加

  • Access-Control-Allow-Origin:和简单请求一样,表示允许的源
  • Access-Control-Allow-Methods:表示允许的后续真实的请求方法
  • Access-Control-Allow-Headers:表示允许改动的请求头
  • Access-Control-Max-Age:告诉浏览器,多少秒内,对于同样的请求源、方法、头,都不需要再发送预检请求了

默认情况下,ajax 的跨域请求并不会附带 cookie,这样一来,某些需要权限的操作就无法进行,不过可以通过简单的配置就可以实现附带 cookie,xhr通过 withCredentials = true 配置,fetch 通过 init 参数对象中的 credentials配置。这样一来该请求就是一个附带身份凭证的请求,会在请求头中添加 cookie 字段。服务器需要在响应头中添加 Access-Control-Allow-Credentials: true即可

**对于附带身份凭证的请求,服务器不得设置 Access-Control-Allow-Origin 的值为***。

参考文章:
Http跨域资源共享 MDN
前端面试必会网络之跨域问题解决

跨域常见的解决方法

http://example.com/2023/02/05/跨域/

作者

徐云飞

发布于

2023-02-05

更新于

2023-02-05

许可协议

评论