- 跨域資源共享(CORS):瀏覽器同源策略中的同源指協議+域名+端口三者完全一致,其中任何一個不同即爲跨域
1. 瀏覽器同源策略是隔離潛在惡意文件的安全機制,限制信息傳遞和使用的邊界,不是信息的保密機制。<img><script><link>以及表單提交都可實現跨域請求,但可能會不同程度受同源策略的限制,因瀏覽器不同而異; 2. 跨域資源共享(CORS)是一個W3C標準,是在客戶端和服務端同時遵循的情況下執行的,整個CORS通信過程,都是瀏覽器自動完成,在編碼上與同源資源共享並無不同(CORS交互中使用WithCredentials除外); 3. 如果客戶端不支持跨域資源共享(CORS),則信息的傳遞和使用將可能受同源策略限制,但服務端返回的任然是正常的HTTP響應; 4. IE未將端口號加入到同源策略的組成部分之中,Chrome 和 Firefox不允許從 HTTPS 的域跨域訪問 HTTP。
下表給出了相對http://store.company.com/dir/page.html同源檢測的示例:
URL 結果 原因 http://store.company.com/dir2/other.html
成功 http://store.company.com/dir/inner/another.html
成功 https://store.company.com/secure.html
失敗 不同協議 ( https和http ) http://store.company.com:81/dir/etc.html
失敗 不同端口 ( 81和80) http://news.company.com/dir/other.html
失敗 不同域名 ( news和store ) - 規避瀏覽器同源策略:以下列舉了一些常見的可用方法
1. document.domain:不同子域下通過設置document.domain爲相同的父級域來共享cookie 和 DOM (iframe) document.domain = "company.com:8080"; 2. 片段識別符(fragment identifier):在使用iframe場景中,父子頁通過URL #後的fragment來跨域傳遞數據 window.onhashchange = function () { var message = window.location.hash; // ... } 3. window.name:無論是否同源,只要在同一個窗口裏,前一個網頁設置了這個屬性,後一個網頁可以讀取它。window.name容量很大,可以放置非常長的字符串 var data = document.getElementById('myIframe').contentWindow.name; 4. window.postMessage(跨文檔通信Cross-document Messaging):這是HTML5新增的API var popup = window.open('http://bbb.com', 'title'); popup.postMessage('Hello World!', 'http://bbb.com'); 5. jsonp:最大特點就是簡單適用,老式瀏覽器全部支持,服務器改造非常小; 6. WebSocket:它使用ws://(非加密)和wss://(加密)作爲協議前綴。該協議不支持同源政策,只要服務器支持,就可以通過它進行跨源通信; 7. Proxy Server:在本域之內增加Proxy Server節點負責域外數據的訪問代理 8. CORS:此處不再贅述
-
跨域資源共享(CORS)請求:通常CORS請求可分爲兩類,一類是簡單請求,另一類則是預檢請求。無論何種請求類型,只要服務端響應中未包含正確的首部如Access-Control-Allow-Origin: http://foo.example等,瀏覽器將報告錯誤。
簡單請求:簡單請求與普通請求相比,多了請求首部字段Origin,形如Origin: http://foo.example,服務端響應時則多了響應首部字段Access-Control-Allow-Origin,形如Access-Control-Allow-Origin: http://foo.example 或者 *。簡單請求須滿足所有下述條件:
- 使用下列方法之一:
GET
HEAD
POST
Content-Type
:僅POST方法的Content-Type值等於下列之一纔算作簡單請求:text/plain
multipart/form-data
application/x-www-form-urlencoded
- Fetch 規範定義了對 CORS 安全的首部字段集合,不得人爲設置該集合之外的其他首部字段。該集合爲:
Accept
Accept-Language
Content-Language
Content-Type
DPR
Downlink
Save-Data
Viewport-Width
Width
預檢請求:需預檢的請求必須首先使用OPTIONS
方法發起一個預檢請求到服務器,以獲知服務器是否允許該實際請求,如果服務端同意,再發送實際請求,這樣可以避免跨域請求對服務器的用戶數據產生未預期的影響。預檢請求須滿足所有下述條件:- 使用了下面任一 HTTP 方法:
PUT
DELETE
CONNECT
OPTIONS
TRACE
PATCH
- 人爲設置了對 CORS 安全的首部字段集合之外的其他首部字段。該集合爲:
Accept
Accept-Language
Content-Language
Content-Type
(but note the additional requirements below)DPR
Downlink
Save-Data
Viewport-Width
Width
-
Content-Type
的值不屬於下列之一:application/x-www-form-urlencoded
multipart/form-data
text/plain
- 使用下列方法之一:
- 跨域資源共享(CORS)附帶身份憑證:默認情況下CORS不會在請求中附帶 HTTP cookies 和 HTTP 認證信息,故需要將 withCredentials 標誌設置爲 true,如下
var invocation = new XMLHttpRequest(); var url = 'http://bar.other/resources/credentialed-content/'; function callOtherDomain(){ if(invocation) { invocation.open('GET', url, true); invocation.withCredentials = true; invocation.onreadystatechange = handler; invocation.send(); } }
但是,如果服務器端的響應中未攜帶
Access-Control-Allow-Credentials: true 或者
Access-Control-Allow-Origin: *
,瀏覽器將不會把響應內容返回給請求的發送者。
- 跨域資源共享(CORS) HTTP首部:CORS所涉及的首部包括響應首部和請求首部,這些首部大多包含同一前綴 “Access-Control-”,Origin除外。更多解釋可參考 HTTP訪問控制(CORS)
- 參考:
1. 瀏覽器的同源策略