JavaScript 的同源策略

同源策略限制了一個源(origin)中加載文本或腳本與來自其它源(origin)中資源的交互方式。javascript

同源定義

若是兩個頁面擁有相同的協議(protocol),端口(若是指定),和主機,那麼這兩個頁面就屬於同一個源(origin)。php

下表給出了相對http://store.company.com/dir/page.html同源檢測的示例:html

URL 結果 緣由
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 失敗 主機名不一樣

參見origin definition for file: URLs.java

源繼承

來自about:blankjavascript:data:URLs中的內容,繼承了將其載入的文檔所指定的源,由於它們的URL自己未指定任何關於自身源的信息。web

IE特例

在處理同源策略的問題上,IE存在兩個主要的不一樣之處。跨域

  • 授信範圍(Trust Zones):兩個相互之間高度互信的域名,如公司域名(corporate domains),不遵照同源策略的限制。
  • 端口:IE未將端口號加入到同源策略的組成部分之中,所以 http://company.com:81/index.html 和http://company.com/index.html  屬於同源而且不受任何限制。

這些例外是非標準的,其它瀏覽器也未作出支持,但會助於開發基於window RT IE的應用程序。瀏覽器

變動源

頁面能夠改變自己的源,但會受到一些限制。腳本能夠設置document.domain 的值爲當前域的一個後綴安全

在同源策略中有一個例外,腳本能夠設置 document.domain 的值爲當前域的一個後綴,若是這樣作的話,短的域將做爲後續同源檢測的依據。例如,假設在http://store.company.com/dir/other.html 中的一個腳本執行了下列語句:cookie

document.domain = "company.com";
 

這條語句執行以後,頁面將會成功地經過對 http://company.com/dir/page.html 的同源檢測。而同理,company.com 不能設置 document.domain 爲othercompany.com.網絡

瀏覽器單獨保存端口號。任何的賦值操做,包括document.domain = document.domain都會以null值覆蓋掉原來的端口號。所以company.com:8080頁面的腳本不能僅經過設置document.domain = "company.com"就能與company.com通訊。賦值時必須帶上端口號,以確保端口號不會爲null。

附註:使用document.domain來安全是讓子域訪問其父域,須要同時將子域和父域的document.domain設置爲相同的值。必需要這麼作,即便是簡單的將父域設置爲其原來的值。沒有這麼作的話可能致使受權錯誤。

 

跨域網絡訪問

同源策略控制了不一樣源之間的交互,例如在使用XMLHttpRequest 或 <img> 標籤時則會受到同源策略的約束。交互一般分爲三類:

  • 一般容許進行跨域寫操做(Cross-origin writes)。例如連接(links),重定向以及表單提交。特定少數的HTTP請求須要添加 preflight
  • 一般容許跨域資源嵌入(Cross-origin embedding)。以後下面會舉例說明。
  • 一般不容許跨域讀操做(Cross-origin reads)。但常能夠經過內嵌資源來巧妙的進行讀取訪問。例如能夠讀取嵌入圖片的高度和寬度,調用內嵌腳本的方法,或availability of an embedded resource.

如下是一些能夠跨域內嵌的資源示例:

  • <script src="..."></script>標籤嵌入跨域腳本。語法錯誤信息只能在同源腳本中捕捉到。
  •  <link rel="stylesheet" href="...">標籤嵌入CSS。因爲CSS的鬆散的語法規則,CSS的跨域須要一個設置正確的Content-Type消息頭。不一樣瀏覽器有不一樣的限制: IEFirefoxChromeSafari (跳至CVE-2010-0051)部分 和 Opera
  •  <img>嵌入圖片。支持的圖片格式包括PNG,JPEG,GIF,BMP,SVG,...
  •  <video> 和 <audio>嵌入多媒體資源。
  •  <object><embed> 和 <applet>的插件。
  • @font-face引入的字體。一些瀏覽器容許跨域字體( cross-origin fonts),一些須要同源字體(same-origin fonts)。
  •  <frame> 和 <iframe>載入的任何資源。站點可使用X-Frame-Options消息頭來阻止這種形式的跨域交互。

實現跨域訪問

使用CORS 來實現跨域訪問。

阻止跨域訪問

  • 阻止跨域寫操做,只要檢測請求中的一個不可測的標記(CSRF token)便可,這個標記被稱爲Cross-Site Request Forgery (CSRF) 標記。必須使用這個標記來阻止頁面的跨站讀操做。
  • 阻止資源的跨站讀取,須要保證該資源是不可嵌入的。阻止嵌入行爲是必須的,由於嵌入資源一般向其暴露信息。
  • 阻止跨站嵌入,確保你得資源不能是以上列出的可嵌入資源格式。多數狀況下瀏覽器都不會遵照Conten-Type消息頭。例如,若是你在<script>標籤中嵌入HTML文檔,瀏覽器仍將HTML解析爲Javascript。When your resource is not an entry point to your site, you can also use a CSRF token to prevent embedding.

跨域腳本API訪問

Javascript的APIs中,如 iframe.contentWindowwindow.parentwindow.open 和 window.opener 容許文檔間直接相互引用。當兩個文檔的源不一樣時,這些引用方式將對 Window  Location對象的訪問添加限制。可使用window.postMessage 做爲替代方案,提供跨域文檔間的通信。

跨域數據存儲訪問

 

存儲在瀏覽器中的數據,如localStorageIndexedDB,以源進行分割。每一個源都擁有本身單獨的存儲空間,一個源中的Javascript腳本不能對屬於其它源的數據進行讀寫操做。

window.name屬性能夠用來臨時存儲數據,能夠跨域訪問。

Cookies使用不一樣的源定義方式。一個頁面能夠爲本域和任何父域設置cookie,只要是父域不是公共後綴(public suffix)便可。Firefox和Chrome使用Public Suffix List決定一個域是不是一個公共後綴(public suffix)。無論使用哪一個協議(HTTP/HTTPS)或端口號,瀏覽器都容許給定的域以及其任何子域名(sub-domains)來訪問cookie。設置cookie時,你可使用Domain,Path,Secure,和Http-Only標記來限定其訪問性。讀取cookie時,不會知曉它的出處。儘管使用安全的https鏈接,任何可見的cookie都是使用不安全的鏈接設置的。

參見

 

 

出自

https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy#.E8.B7.A8.E5.9F.9F.E6.95.B0.E6.8D.AE.E5.AD.98.E5.82.A8.E8.AE.BF.E9.97.AE

相關文章
相關標籤/搜索