感谢浏览,本文所有内容均为自己在网络中学习所得,如果您发现一些错误,可以在评论区提出,谢谢
一、什么是跨域?
1. URL 的构成
URL 由协议、ip 地址、端口号组成,格式为:协议://IP地址:端口号
比如 https://cn.bing.com/search?q=hello
这个网址,协议是 https://
,域名是 cn.bing.com
,端口是 80
(默认端口可以省略)
2. 什么是跨域
现阶段的 Web 应用开发几乎都会涉及到前后端分离模式,该模式的前端与后端通过 API 进行通信,这样的开发模式维护起来很方便,但是会带来请求跨域的问题
所谓跨域就是从 A
向 B
发请求,如若他们的协议、域名、端口有一处不同,就涉及到了请求跨域的问题
出于安全考虑(比如 CSRF 攻击),浏览器设置了同源策略,会禁止进行跨域请求,同源政策规定,AJAX 请求只能发给同源的网址,否则就报错
需要注意的是,跨域问题并不是请求错误,而是浏览器的一种限制手段,可以通过查看 Network 发现,请求能够正常发送、响应,只是响应的内容浏览器不会正常解析
3. 跨域的举例判断
URL1 | URL2 | 是否同源 | 原因 |
---|---|---|---|
http://www.a.com/ |
http://www.a.com/temp/ |
是 | 协议、域名、端口相同 |
http://www.a.com:8111/a.js |
http://www.a.com/a.js |
否 | 端口不同(默认 80 端口) |
http://www.a.com/a.js |
https://www.a.com/a.js |
否 | 协议不同 |
http://www.a.com/a.js |
http://www.b.com/a.js |
否 | 域名不同 |
二、常见的跨域问题解决方法
同源政策规定,AJAX请求只能发给同源的网址,否则就报错,常见的有三种方法规避这个限制
(1)JSONP
(2)CORS
(3)同源的代理服务器
1. JSONP
JSONP 是服务器与客户端跨源通信的常用方法,最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小,利用的是 <script>
标签的 src
属性请求无跨域问题的原理,但只能发送 get
请求
大致的工作流程如下
- 网页动态插入
<script>
元素,由它向跨源网址发出请求 - 服务器收到请求后,将数据放在一个指定名字的回调函数里响应到前端
2. CORS
CORS 是一个 W3C 标准,全称是”跨域资源共享”(Cross-origin resource sharing),是跨源 AJAX 请求的根本解决方法,相比JSONP只能发GET
请求,CORS 允许任何类型的请求
大致的工作流程如下
- 浏览器请求主机
A
,但是请求会正常发送到主机A
- 主机
A
正常接收请求、响应请求 - 但是主机
A
响应数据时会在响应报文里添加几个响应头,再将数据返回给浏览器 - 浏览器接收到响应的数据时,如果看到了这几个响应头,会正常解析数据
- 也即实现了浏览器向跨源服务器发出请求,从而克服了请求只能同源使用的限制
具体的细节可以参考:跨域资源共享 CORS 详解
3. 同源的代理服务器【推荐】
举例:将前端项目部署到 Nginx 服务上,使得前端项目访问 Nginx 服务是同源请求,之后 Nginx 将请求转发到后端服务器即可
同源策略是浏览器的安全策略,不是HTTP协议的一部分,所以可以让浏览器请求同源服务器,再由后者请求外部服务的资源
大致的工作流程如下
- 主机
A
请求主机B
- 出现了跨域问题
- 通过
nginx
配置一个代理服务器C
(域名、端口均与主机A
相同)做一个跳板,后续将请求转发到主机B
此时主机A
与主机C
是同源的,没有跨域问题 - 主机
C
再将请求转发到主机B
,虽然主机C
与 主机B
不是同源的,但是这两个主机之间的通信已经不涉及浏览器,不受同源策略的限制,所以可以正常通信,实现了反向代理访问到主机B