资讯专栏INFORMATION COLUMN

浏览器同源政策以及JS跨域

zeyu / 923人阅读

摘要:浏览器同源政策以及跨域同源是指协议相同域名相同端口相同。同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。参考文献浏览器同源政策及其规避方法详解跨域问题

浏览器同源政策以及JS跨域

同源是指协议相同、域名相同、端口相同。同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。

同源策略主要限制下面三种情况

Cookie 无法读取

DOM 无法获得

AJAX 请求不能发送

同源策略的本意是为了保证用户的信息安全。但有时也会带来不便,下面我们来看一下怎样规避同源的限制。

Cookie

是服务器写入浏览器的一小段信息,只有同源的网页才能共享。

当两个网页的一级域名相同,只是二级域名不同的时候,我们可以通过设置document.domain来共享cookie
具体操作如下:

// 这两个网页的一级域名是相同的 
http://h1.test.com
http://h2.test.com

//为两个页面设置相同的 document.domain
document.domain = "test.com"

// 这样两个网页就能共享`Cookie`

document.domain 不能随意设置,只能把document.domain设置成自身或更高一级的父域。

跨域文档通信

如果两个网页不同源,就无法拿到对方的DOM,也无法进行通信。典型的例子是iframe窗口和window.open方法打开的窗口,它们与父窗口无法通信。

如果两个窗口一级域名相同,只是二级域名不同,那么设置上一节介绍的document.domain属性,就可以规避同源政策,拿到DOM

关于通信,我们来看一下两种解决方案:

片段识别符

片段标识符(fragment identifier)指的是,URL#号后面的部分,如果只是改变片段标识符,页面不会重新刷新。

//父窗口可以把信息,写入子窗口的片段标识符
var src = originURL + "#" + data;
document.getElementById("myIFrame").src = src;

//子窗口通过监听hashchange事件得到通知
window.onhashchange = checkMessage;

function checkMessage() {
  var message = window.location.hash;
  // ...
}


//同样的,子窗口也可以改变父窗口的片段标识符
parent.location.href= target + "#" + hash;
window.postMessage

window.postMessage 是HTML5为了解决这个问题,引入了一个全新的API,无论两个窗口是否同源,都允许一个窗口向另一个窗口发送数据。

语法:

// otherWindow 其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象

//message 将要发送到其他 window的数据

//targetOrigin 接收消息的窗口的源(origin)

otherWindow.postMessage(message, targetOrigin)

其他window可以监听message

//监听 message 事件

window.addEventListener("message", receiveMessage, false);

//事件对象有一些常用的属性

//data 从其他 window 中传递过来的对象

//origin 消息发送方窗口的 origin

//source 对发送消息的窗口对象的引用

function receiveMessage(event){
    var origin = event.origin;
    
    //对发送消息的源进行验证
    
   if (origin !== "http://example.org:8080")
      return;

  // ...
}

实例:

窗口A : http://xiaoxiong.com
窗口B : http://miaomiao.com
显然这两个窗口不同源,不能通信,现在我们用postMessage进行通信。

//Awindow、Bwindow分别表示对 A B 窗口对象的引用
//B窗口向A窗口发消息
//如果A窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,消息就不能发送成功
//注意是用 Awindow 调用 postMessage 方法
 Awindow.postMessage("hello!","http://xiaoxiong.com");
 
 //在A中设置监听事件
 window.addEventListener("message", receiveMessage, false);
 
 function receiveMessage(event){
    console.log(event.origin);//http://miaomiao.com
    console.log(event.source);// Bwindow
    console.log(event.data);// hello!
    
} 
AJAX

AJAX请求是我们经常用到的异步请求方法,但是AJAX请求是不能跨域的。

下面我们看一下常见的AJAX跨域方法

JSONP

基本思想是,网页通过添加一个

阅读需要支付1元查看
<