同源策略

LeoYao發表於2020-07-13

什麼是同源

  • 協議相同
  • 域名相同
  • 埠相同(實際上,同一網域不同埠,可以相互讀取 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 可以傳送任何請求

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章