-
JSONP跨域
-
iframe+domain跨域
-
nginx反向代理跨域
-
cors跨域
-
通过window.name跨域
-
postMessage跨域
JSONP跨域:
虽然jsonp实现跨域方式很简单,但是只支持get请求,对传输的数据量有一定限制。
iframe+domain跨域:
在页面www.damonare.cn/a.html 中设置document.domain。CORS:
<iframe id = "iframe" src="http://damonare.cn/b.html" onload = "test()"></iframe>
document.domain = 'damonare.cn';//设置成主域
function test(){ alert(document.getElementById('iframe').contentWindow);
//contentWindow 可取得子窗口的 window 对象
}
cors跨域:
是一份浏览器技术的规范,提供了 Web 服务从不同网域传来沙盒脚本的方法,以避开浏览器的同源策略,是 JSONP 模式的现代版。与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。用 CORS 可以让网页设计师用一般的 XMLHttpRequest,这种方式的错误处理比 JSONP 要来的好。另一方面,JSONP 可以在不支持 CORS 的老旧浏览器上运作。现代的浏览器都支持 CORS。
具体如下
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
通过window.name跨域
可以看到,如果在一个标签里面跳转网页的话,我们的 window.name 是不会改变的。
基于这个思想,我们可以在某个页面设置好 window.name 的值,然后跳转到另外一个页面。在这个页面中就可以获取到我们刚刚设置的 window.name 了。
<iframe id="iframe" src="http://www.google.com/iframe.html"></iframe>
var iframe = document.getElementById('iframe');
var data = '';
iframe.onload = function() {
iframe.onload = function(){
data = iframe.contentWindow.name;
}
iframe.src = 'about:blank';
};
或者将里面的 about:blank 替换成某个同源页面(about:blank,javascript: 和 data: 中的内容,继承了载入他们的页面的源。)
这种方法与 document.domain 方法相比,放宽了域名后缀要相同的限制,可以从任意页面获取 string 类型的数据。
postMessage跨域:
window.postMessage() 方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议,端口号以及主机 (两个页面的模数 Document.domain设置为相同的值) 时,这两个脚本才能相互通信。window.postMessage() 方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。
本质上说postMessage()是基于消息事件机制来实现跨域通信,它隶属于消息窗体本身,比如window以及window内嵌的frame的window,基本使用形式如下:
someWindow.postMessage(message, targetOrigin, [transfer]);
参数介绍:
- someWindow 窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames
- message 将要发送到其他 window的数据。意味着你可以不受什么限制的将数据对象安全的传送给目标窗口而无需自己序列化
- targetOrigin 通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)。不提供确切的目标将导致数据泄露等安全问题
- transfer 是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权
我们可以通过如下方式来监听message:
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event){
let origin = event.origin || event.originalEvent.origin;
if (origin !== "http://aaa:8080")
return;
// ...
console.log(event.data)
}