同源政策(Same-origin policy)

同來源政策限制了程式碼和不同網域資源間的互動。

同源定義

所謂同源是指兩份網頁具備相同協定、埠號(如果有指定)以及主機位置,下表提供了一些例子展示那些來源和http://store.company.com/dir/page.html屬於同源:

URL Outcome Reason
http://store.company.com/dir2/other.html 同源  
http://store.company.com/dir/inner/another.html 同源  
https://store.company.com/secure.html 不同源 協定不同
http://store.company.com:81/dir/etc.html 不同源 埠號不同
http://news.company.com/dir/other.html 不同源 主機位置不同

另外請參考file來源定義: URL。See also origin definition for file: URLs.

Cookie的來源定義和上述不一樣。

變更來源

網頁能夠有限地變更來源,我們可以將document.domain存為目前網域後半部,然後較短的網域就會作為之後來源檢查,譬如我們在http://store.company.com/dir/other.html的文件裡執行以下程式碼:

document.domain = "company.com";

執行完後,網頁能以http://company.com/dir/page.html通過同源檢查。然而基於同源檢查,company.com無法將document.domain存為othercompany.com。

任何變更document.domain行為,包括document.domain = document.domain都會導致埠號重置為null,因此無法只藉由執行document.domain = "company.com"讓company.com:8080和company.com互動,必須兩邊都重新設定好讓埠號都一致重置為null。

Note: 為了讓子網域可以安全的存取其父網域安全地,我們需要一起改變子網域和父網域的document.domain成同值,即使只是要把父網域設回原始值這也是必要的,如果不這麼做將會導致允許錯誤。

跨來源網路存取

同源政策控制了兩個不同網域來源互動,例如當使用XMLHttpRequest。這些互動可分為以下三類:

  • 跨來源寫(Cross-origin writes)通常被允許,例如有連結、重新導向以及表單送出。少數某些HTTP請求需要先導請求
  • 跨來源嵌入(Cross-origin embedding)通常被允許,例子請參照下方。
  • 跨來源讀取(Cross-origin read) 通常不被允許,不過通常可以藉由嵌入來繞道讀取,例如嵌入影像寬高讀取、嵌入程式碼或嵌入資源

下面是一些能跨來源嵌入的資源:

  • <script src=”…”></script>內的Javascript,但語法錯誤訊息只限於同源程式碼腳本。
  • CSS的<link rel="stylesheet" href="...">,由於CSS寬鬆語法規則,跨來源CSS要求正確的Content-Type標頭。限制在瀏覽器間各有差異: IE, Firefox, Chrome, Safari (請至CVE-2010-0051)以及Opera.
  • <img>的影像;支援格式有PNG, JPEG, GIF, BMP, SVG等等
  •  <video><audio>媒體檔案
  •  <object>, <embed><applet>的外掛
  • @font-face 的字型;有些瀏覽器允許跨來源字型,有些則不。
  •  <frame>以及<iframe>中的內容;如果一個網站想要避免跨來源載入互動,可以藉由X-Frame-Options標頭避免。

如何允許跨來源存取

使用CORS允許跨來源存取

如何阻擋跨來源存取

  • 藉由檢查請求中包含的無法猜測的特殊記號(token)可以避免跨來源寫入,還有跨來源讀取知道此記號的網頁,這個記號即為跨站偽造(Cross-Site Request Forgery, CSRF)記號。
  • 確保資源無法被嵌入來防止跨來源讀取。
  • 為了防止跨來源嵌入,請確保資源不被解讀為上述可嵌入格式之一;瀏覽器通常不會理會Content-Type,比如說有一個指向HTML文件的<script>標籤,瀏覽器還是會嘗試解析該HTML文件為Javascript;當你的資源不是網站進入點,可以使用CSRF記號。

跨來源程式腳本存取

Javascript API例如iframe.contentWindow, window.parent, window.open以及window.opener,允許文件之間直接互相參照,當兩份文件的來源不同,參照存取WindowLocation物件將受到限制;一些瀏覽器比規範准許存取更多屬性。文件間的溝通也可以改用window.postMessage來進行。

延伸閱讀

Original Document Information

  • Author(s): Jesse Ruderman

 

Document Tags and Contributors

Contributors to this page: foxbrush
最近更新: foxbrush,