【尚硅谷】跨域解决方案梳理
【尚硅谷】跨域解决方案梳理
時光尚硅谷视频:禹神:一小时彻底搞懂跨域&解决方案
尚硅谷文档:跨域问题梳理
1、浏览器的同源策略
1.1、同源策略概述
同源策略是 浏览器 为确保 资源安全 ,而遵循的一种策略,该策略对 访问资源 进行了一些限制。
W3C 上对同源策略的说明:Same origin policy。
1.2、什么是源(origin)?
1、 源的组成部分
2、下面表格中,只有最后一行的两个源是同源。
3、同源请求
4、非同源请求
总结:『所处源』与『目标源』不一致,就是『非同源』,又称『异源』或『跨域』。
2、跨域会受到哪些限制
例如有两个源:『源A』和『源B』,它们是『非同源』的,那么 浏览器 会有如下限制:
2.1、限制DOM访问
『源A』的脚本 不能访问『源B』的 DOM。
1 | <!-- <iframe id="framePage" src="./demo.html"></iframe> --> |
2.2、限制 Cookie 访问
『源A』不能访问『源B』的 cookie。
1 | <iframe id="baidu" src="http://www.baidu.com" width="500" height="300"></iframe> |
2.3、限制 Ajax 获取数据
『源A』可以给『源B』发请求,但是 无法获取『源B』响应的数据。
1 | const url = 'https://www.toutiao.com/hot-event/hot-board/?origin=toutiao_pc' |
备注:在上述限制中,浏览器对 Ajax 获取数据的限制是影响最大的一个,且实际开发中经常遇到。
3、几个注意点
1、跨域限制仅存在浏览器端,服务端不存在跨域限制。
2、即使跨域了,Ajax 请求也可以正常发出,但响应数据不会交给开发者。
3、<link>
、<script>
、<img>
…… 这些标签发出的请求也可能跨域,只不过浏览器对标签跨域不做严格限制,对开发几乎无影响。
4、CORS 解决 Ajax 跨域问题
4.1、CORS 概述
CORS 全称:Cross-Origin Resource Sharing
(跨域资源共享),是用于控制 浏览器校验 跨域请求的一套规范,服务器依照 CORS 规范,添加特定 响应头 来控制浏览器校验,大致规则如下:
- 服务器明确表示 拒绝跨域 请求,或 没有表示 ,则浏览器校验 不通过 。
- 服务器明确表示 允许跨域 请求,则浏览器校验 通过 。
备注说明:使用 CORS 解决跨域是最正统的方式,且要求服务器是“自己人”。
4.2、CORS 解决简单请求跨域
整体思路:服务器在给出响应时,通过添加Access-Control-Allow-Origin
响应头,来明确表达允许某个源发起跨域请求,随后浏览器在校验时,直接通过。
服务端核心代码(以express框架为例):
1 | // 处理跨域中间件 |
4.3、简单请求与复杂请求
CORS 会把请求分为两类,分别是:① 简单请求、② 复杂请求。
关于预检请求:
发送时机:预检请求在实际 跨域请求 之前发出,是由 浏览器自动发起 的。
主要作用:用于向服务器 确认 是否允许接下来的跨域请求。
基本流程:先发起
OPTIONS
请求,如果 通过 预检, 继续发起 实际的跨域请求。请求头内容:一个
OPTIONS
预检请求,通常会包含如下 请求头 :
4.4、CORS 解决 复杂请求 跨域
1、第一步:服务器先 通过 浏览器的 预检请求,服务器需要返回如下 响应头 :
2、第二步:处理实际的 跨域请求(与处理简单请求跨域的方式相同)
服务端核心代码:
1 | // 处理预检请求 |
4.5、 借助 cors 库快速完成配置
上述的配置中需要自己配置响应头,或者需要自己手动封装中间件,借助cors库,可以更方便完成配置\
安装cors
1 | npm i cors |
简单配置cors
1 | app.use(cors()) |
完整配置cors
1 | // cors中间件配置 |
5、JSONP 解决跨域问题
1、JSONP 概述: JSONP 是利用了<script>
标签可以跨域加载脚本,且不受严格限制的特性,可以说是程序员智慧的结晶,早期一些浏览器不支持 CORS 的时,可以靠 JSONP 解决跨域。
2、基本流程:
- 第一步:客户端创建一个
<script>
标签,并将其src属性设置为包含跨域请求的 URL,同时准备一个回调函数,这个回调函数用于处理返回的数据。 - 第二步:服务端接收到请求后,将数据封装在回调函数中并返回。
- 第三步:客户端的回调函数被调用,数据以参数的形势传入回调函数。
3、图示
4、代码示例:
1 | <button onclick="getTeachers()">获取数据</button> |
5、jQuery 封装的 jsonp
1 | $.getJSON('http://127.0.0.1:8081/teachers?callback=?',(data)=>{ |
6、配置代理解决跨域
6.1、自己配置代理服务器
借助http-proxy-middleware
配置代理
1 | const { createProxyMiddleware } = require('http-proxy-middleware'); |