浏览器的同源策略
同源策略限制了从一个源加载的文档和脚本如何与另外一个源的资源进行交互( 对于当前页面来说页面存放的 JS 文件的域不重要,重要的是加载该 JS 页面所在什么域),这是一个用于隔离潜在恶意文件的重要安全机制。
- 通常浏览器允许进行跨域写操作(Cross-origin writes),如链接,重定向;
- 通常浏览器允许跨域资源嵌入(Cross-origin embedding),如 img、script 标签;
- 通常浏览器不允许跨域读操作(Cross-origin reads)。
什么是同源?
- 协议相同
- 域名相同
- 端口相同
跨域解决方案
通常,最常用的跨域方式有以下三种:JSONP、CORS、postMessage。
JSONP
【实现原理】
虽然因为同源策略的影响,不能通过XMLHttpRequest请求不同域上的数据(Cross-origin reads)。但是,在页面上引入不同域上的js脚本文件却是可以的(Cross-origin embedding)。因此在js文件载入完毕之后,触发回调,可以将需要的data作为参数传入。
【实现方式(前后端配合)】
a.com通过script标签去b.com获取资源(加载资源不受同源策略限制)
<script src="http://b.com:8080/getWeather?callback=showdata">
</script>
b.com后台判断请求的query,返回数据showdata(data)字符串,其中data就是我们要获取的数据
if (pathObj.query.callback === "showdata") {
res.end("showdata" + "(" + data + ")")
}
我们就可以在a.com去定义操作数据的方法
<script>
function showdata(data) {
console.log(data)
}
</script>
CORS
CORS 全称是跨域资源共享(Cross-Origin Resource Sharing),是一种 ajax 跨域请求资源的方式,支持现代浏览器,
【实现原理】
IE支持10以上。当你使用 XMLHttpRequest 发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin; 浏览器判断该相应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。
【实现方式】
在后台设置响应头,同意http://a.com:8080源来请求数据
res.setHeader('Access-Control-Allow-Origin','http://a.com:8080')
a.com的请求头会带上自己的源
Origin: http://a.com:8080
如果匹配则可以共享资源
postMessage
HTML5为了解决这个问题,引入了一个全新的API:跨文档通信 API(Cross-document messaging)。这个API为window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源。
【实现方式】
postMessage方法的第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源(origin),即"协议 + 域名 + 端口"。也可以设为*,表示不限制域名,向所有窗口发送。
popup.postMessage('Hello World!', 'http://b.com:8080/index.html');
b.com可以通过监听message事件来获取数据
window.addEventListener('message', function(e) {
console.log(e.data);
},false);
降域(document.domain)
还有一种情况,就是一级域名相同,只是二级域名不同
举例来说,A网页是http://w1.example.com/a.html
,B网页是http://w2.example.com/b.html
,那么只要设置相同的document.domain
,两个网页就可以共享Cookie。
document.domain = 'example.com';
注意,这种方法只适用于 Cookie 和 iframe 窗口
网友评论