前端杂谈 · Web

同源策略

•̀.̫•́✧ · 7月26日 · 2020年本文1698字 · 阅读5分钟125

什么是同源

  • 协议相同
  • 域名相同
  • 端口相同(实际上,同一网域不同端口,可以相互读取 Cookie)

同源限制范围

如果非同源,共有三个行为受到限制

(1)无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
(2)无法接触非同源网页的 DOM
(3)无法向非同源地址发送 AJAX 请求(可以发送,但是浏览器拒绝接受响应)

Cookie

Cookie 是服务器写入浏览器的一小段信息,只有同源的网页才能共享。如果两个网页一级域名相同,只是次级域名不同,浏览器允许通过设置 document.domain 共享 Cookie

iframe 和多窗口通信

只有在同源的情况下,父窗口和子窗口才能通信;如果跨域,就无法拿到对方的 DOM
对于完全不同源的网站,目前有两种方法,可以解决跨域窗口的通信问题

  • 片段识别符
  • 跨文档通信 API

### 片段识别符
片段识别符指的是,URL 的 # 号后面的部分。父窗口把所要传递的信息,写入 iframe 窗口的片段标识符。
子窗口通过监听 hashchange 事件得到通知

postMessage

跨文档通信 API,允许跨窗口通信,不论这两个窗口是否同源。

// 父窗口打开一个子窗口
var popup = window.open('http://bbb.com', 'title');
// 父窗口向子窗口发消息
popup.postMessage('Hello World', 'http://bbb.com');

子窗口向父窗口发送信息的写法类似

window.opener.postMessage('Nice to see you', 'http://aaa.com')

父窗口和子窗口都可以通过 message 事件,监听到对方的消息

// 父窗口和子窗口都可以用下面的代码
//监听 message 消息
window.addEventListener('message', function (e) {
    console.log(e.data)
}, false)

AJAX

同源策略规定,AJAX 请求只能发给同源的网址,否则就报错
有四种方法规避这种限制

JSONP
WebSocket
CORS
架设服务器代理 (浏览器请求同源服务器,再由后者请求外部服务)

JSONP

JSONP 最大特点是简单易用,没有兼容性问题
操作流程:

1.网页添加一个 <script> 元素,向服务器请求一个脚本,这不受同源政策限制,可以跨域请求

<script src="http://api.foo.com?callback=bar"></script>

请求网址有一个 callback 参数,用来告诉服务器,客户端的回调函数名称(bar)

2.服务器收到请求后,拼接一个字符串,将 JSON 数据放在函数名里面,作为字符串返回

3.客户端会将服务器返回的字符串,作为代码解析,因为浏览器认为,这是 <script> 标签请求的脚本内容。这时,客户端只要定义 bar() 函数,就能在该函数体内,获得服务器返回的 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 标准,属于跨源 AJAX 请求的根本解决方法。相比 JSONP 只能发 GET 请求,CORS 可以发送任何请求

0 条回应