编者注:关于跨域的文章,之前分享过很多,来看看这篇前端跨域解决方案,由简及深介绍各种存在的跨域请求解决方案,包括 document.domain, location.hash, window.name, window.postMessage, JSONP, WebSocket, CORS。
原文:hijiangtao.github.io
同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。但是有时候跨域请求资源是合理的需求,本文尝试从多篇文章中汇总至今存在的所有跨域请求解决方案。
跨域请求
首先需要了解的是同源和跨源的概念。对于相同源,其定义为:如果协议、端口(如果指定了一个)和主机对于两个页面是相同的,则两个页面具有相同的源。只要三者之一任意一点有不同,那么就为不同源。当一个资源从与该资源本身所在的服务器的域或端口不同的域或不同的端口请求一个资源时,资源会发起一个跨域 HTTP 请求。而有关跨域请求受到限制的原因可以参考如下 MDN 文档片段:
跨域不一定是浏览器限制了发起跨站请求,而也可能是跨站请求可以正常发起,但是返回结果被浏览器拦截了。最好的例子是 CSRF 跨站攻击原理,请求是发送到了后端服务器无论是否跨域!注意:有些浏览器不允许从 HTTPS 的域跨域访问 HTTP,比如 Chrome 和 Firefox,这些浏览器在请求还未发出的时候就会拦截请求,这是一个特例。
解决方法汇总
以下我们由简及深介绍各种存在的跨域请求解决方案,包括 document.domain, location.hash, window.name, window.postMessage, JSONP, WebSocket, CORS。
document.domain
document.domain 的作用是用来获取/设置当前文档的原始域部分,例如:
// 对于文档 www.example.xxx/good.html
document.domain="www.example.xxx"
// 对于URI http://developer.mozilla.org/en/docs/DOM
document.domain="developer.mozilla.org"
如果当前文档的域无法识别,那么 domain 属性会返回 null。
在根域范围内,Mozilla允许你把domain属性的值设置为它的上一级域。例如,在 developer.mozilla.org 域内,可以把domain设置为 "mozilla.org" 但不能设置为 "mozilla.com" 或者"org"。
因此,若两个源所用协议、端口一致,主域相同而二级域名不同的话,可以借鉴该方法解决跨域请求。
比如若我们在 http://a.github.io 页面执行以下语句:
document.domain = "github.io"
那么之后页面对 github.io 发起请求时页面则会成功通过对 github.io 的同源检测。比较直接的一个操作是,当我们在a.github.io 页面中利用 iframe 去加载 github.io 时,通过如上的赋值后,我们可以在 a.github.io 页面中去操作 iframe 里的内容。
我们同时考虑另一种情况:存在两个子域名 a.github.io 以及 b.github.