由于考虑到安全性问题,html 的同源策略不允许 JavaScript 进行跨域操作,但是随着 web 端功能越来越多,对跨域需求逐渐增大,于是乎便催生了很多解决跨域的方法,通过网络搜索和资料查询,主要比较常见的解决方案有以下几种:
一,设置 document.domain
原理:相同主域名下不同子域页面,通过设置 document.domain 让他们同域;
限制:此方法只适用与跨子域的,对于跨父域名,仍然不可行,且需要载入 iframe 页面.
上述代码所在的 URL 是
// url http://bentos.com/foo
var ifr = document.createElement('iframe');
ifr.src = 'http: //b.bentos.com/foo';
ifr.onload = function() {
var ifrdoc = ifr.contentDocument || ifr.contentWindow.document;
ifrdoc.getElementsById("foo").innerHTML);
};
ifr.style.display = 'none';
document.body.appendChild(ifr);
http://bentos.com/foo
,它对
http://b.bentos.com/bar
的 DOM 访问要求后者将 document.domain 往上设置一级
二,jsonp
// URL http://b.bentos.com/bar
document.domain = 'bentos.com'
// URL: http://b.bentos.com/foo
var data = {
foo: 'bar',
bar: 'foo'
};
callback(data);
原理:<script> 是可以跨域的,而且在跨域脚本中可以直接回调当前脚本的函数.
限制:需要创建一个 DOM 对象并且添加到 DOM 树,只能用于 GET 方法
三,navigation 对象
// URL: http://b.bentos.com/foo
var data = {
foo: 'bar',
bar: 'foo'
};
callback(data);
// URL: http://bentos.com/foo
var callback = function(data) {
// 处理跨域请求得到的数据
};
var script = $('<script>', {
src: 'http://b.bentos.com/bar'); $('body').append(script);
原理:iframe 之间是共享 navigator 对象的,用它来传递信息
要求:IE6/7
有些人注意到了 IE6/7 的一个漏洞:iframe 之间的 window.navigator 对象是共享的. 我们可以把它作为一个 Messenger,通过它来传递信息.比如一个简单的委托:
与 document.navigator 类似,window.name 也是当前窗口所有页面所共享的.也可以用它来传递信息.
// bentos.com
navigation.onData() {
// 数据到达的处理函数
}
typeof navigation.getData === '
function' || navigation.getData()
// baidu.com
navigation.getData = function() {
$.get(' / path / under / baidu.com').success(function(data) {
typeof navigation.onData === '
function' || navigation.onData(data)
});
}
四,window.postMessage
原理:HTML5 允许窗口之间发送消息
限制:浏览器需要支持 HTML5,获取窗口句柄后才能相互通信
这是一个安全的跨域通信方法,
postMessage(message, targetOrigin)
也是 HTML5 引入的特性. 可以给任何一个 window 发送消息,不论是否同源.第二个参数可以是 * 但如果你设置了一个 URL 但不 相符,那么该事件不会被分发.看一个普通的使用方式吧:
注意 IE8 及小于 IE8 的版本不支持 addEventListener,需要使用 attachEvent 来监听事件.参见: 事件处理中的 this:attachEvent, addEventListener, onclick
// URL: http://bentos.com/foo
var win = window.open('http://b.com/bar');
win.postMessage('Hello, bar!', 'http://b.com');
// URL: http://baidu.com/bar
window.addEventListener('message',function(event) {
console.log(event.data);
});
五,跨域资源共享(CORS)
原理:服务器设置
Access - Control - Allow - Origin
HTTP 响应头之后,浏览器将会允许跨域请求
限制:浏览器需要支持 HTML5,可以支持 POST,PUT 等方法
例如,从 http://a.com 要访问 http://b.com 的数据,通常情况下 Chrome 会因跨域请求而报错:
1 XMLHttpRequest cannot load http://b.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://a.com' is therefore not allowed access.
错误原因是被请求资源没有设置
Access - Control - Allow - Origin
,所以我们在 b.com 的服务器中设置这个响应头字段即可:
Access - Control - Allow - Origin: *#允许所有域名访问,或者Access - Control - Allow - Origin: http: //a.com # 只允许所有域名访问
在 Html5 出来之前,跨域采用常见方法为 jsonp,jQuery 也给出了支持. 值得注意的是它只是 Hack,并没有产生额外的安全问题. 因为 JSONP 要成功获取数据,需要跨域资源所在服务器的配合,比如资源所在服务器需要自愿地回调一个合适的函数,所以服务器仍然有能力控制资源的跨域访问.
跨域的正道还是要使用 HTML5 提供的 CORS 头字段以及 window.postMessage, 可以支持 POST, PUT 等 HTTP 方法,从机制上解决跨域问题. 值得注意的是
Access - Control - Allow - Origin
头字段是资源所在服务器设置的, 访问控制的责任仍然是在提供资源的服务器一方,这和 JSONP 是一样的道理.
来源: http://www.bubuko.com/infodetail-2460047.html