跨域问题大总结
一. 同源和同源策略
1 同源
如果两个URL具有相同的协议、域名、和端口号,则说这两个URL同源。
2 同源策略
浏览器默认两个相同的源之间可以互相访问资源和操作DOM。两个不同源之间若想要互相访问资源或者操作DOM,就会有一套基础的安全策略的制约,我们把这称之为同源策略。简言之就是从一个源加载的文档或脚本默认不能访问另外一个源的资源。
2.1 同源策略的主要表现
- 第一个 DOM层面
同源策略限制了来自不同源的JavaScript脚本对当前DOM对象读和写的操作。
如果两个页面是同源关系,那么可以在第二个页面中操作第一个页面的DOM,比如将第一个页面隐藏掉。如果是不同源的页面,则无法操作DOM。 - 第二个 数据层面
同源策略限制了不同源的站点无法读取当前站点的Cookie、IndexDB、LocalStorage等数据。 - 第三个网络层面
同源策略限制了通过XMLHttpRequest等方式通过将站点的数据发送给不同源的站点。
2.2 哪些不受同源策略的影响
1. 页面中链接(例如页面的<a href="http://www.w3school.com.cn">W3School</a>
)、重定向和表单提交不受同源策略限制
2. 跨域资源的引入不受同源策略的限制,但是js读不到其中的内容。<script src="..."></script>,<img>,<link>,<iframe>
等。
3 如何解决跨域问题
3.1 跨文档消息机制
根据前面说的不同源的页面无法互相操纵DOM。在实际应用中,经常会需要两个不同源的DOM之间进行通信,于是浏览器又引入跨文档消息机制,可以通过window.postMessage的JavaScript接口来和不同源的DOM进行通信。这种方式通常用于获取嵌入页面中的第三方页面数据。一个页面发送消息,另一个页面判断来源并接收消息。
// 发送消息端
window.parent.postMessage('message', 'http://test.com')
// 接收消息端
var mc = new MessageChannel()
mc.addEventListener('message', event => {
var origin = event.origin || event.originalEvent.origin
if (origin === 'http://test.com') {
console.log('验证通过')
}
})
3.2 CORS跨域资源共享
CORS机制可以解决同源策略网络层面的问题,它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
此部分看阮一峰关于跨域资源共享 CORS 的描述最为清楚。🔗跨域资源共享 CORS 详解
3.3 JSONP
JSONP 的原理很简单,就是利用 <script>
标签没有跨域限制的漏洞。通过 <script>
标签指向一个需要访问的地址并提供一个回调函数来接收数据当需要通讯时。
<script src="http://domain/api?param1=a¶m2=b&callback=jsonp"></script>
<script>
function jsonp(data) {
console.log(data)
}
</script>
3.4 代理服务器
同源策略是浏览器需要遵循的标准,而如果是请求都发给代理服务器代理服务器再向后端服务器请求就可以规避跨域的问题。
例如用nginx做代理服务器。
// 配置nginx
server{
# 监听80端口
listen 80;
# 域名是localhost
server_name localhost;
#凡是localhost:8080/api这个样子的,都转发到真正的服务端地址http://localhost:8080
location ^~ /api {
proxy_pass http://localhost:8080;
}
}