同源政策、跨域

101 阅读2分钟

同源政策

同源

A网页设置的Cookie/localStorage等,B网页不能打开,除非这两个网页同源

  1. 协议相同
  2. 域名相同
  3. 端口相同

同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
不同网站之间不会共享Cookie等信息,比如微博无法获取知乎登录用户的Cookie

限制范围

如果不是同源,以下三种行为受到限制:

  1. CookieLocalStorageIndexDB无法读取
  2. DOM无法获得
  3. AJAX请求不能发送

规避同源:一级域名相同,只有二级域名不相同

Cookie

两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置document.domain共享Cookie
A网页是http://w1.example.com/a.html,B网页是http://w2.example.com/b.html,那么只要设置相同的document.domain,两个网页就可以共享Cookie
以下方法只适用于Cookieiframe窗口:

document.domain = 'example.com';

//A设置cookie
document.cookie = "test1=hello";

//B读取cookie
var allCookie = document.cookie;

规避同源:完全不同源

iframe

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

完全不同源的网站,目前有三种方法,可以解决跨域窗口的通信问题

  1. 片段识别符(fragment identifier)
  2. window.name
  3. 跨文档通信API(Cross-document messaging)

片段识别符

window.name

window.postMessage

AJAX

以下三种方法规避限制:

  1. JSONP
  2. WebSocket
  3. CORS

JSONP

网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。

//网页动态插入<script>元素,由它向跨源网址发出请求

function addScriptTag(src) {
  var script = document.createElement('script');
  script.setAttribute("type","text/javascript");
  script.src = src;
  document.body.appendChild(script);
}

window.onload = function () {
  addScriptTag('http://example.com/ip?callback=foo');
}

function foo(data) {
  console.log('Your public IP address is: ' + data.ip);
};

WebSocket

WebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。

CORS

CORS是一个W3C标准,全称是跨域资源共享(Cross-origin resource sharing)
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。