一.什么是跨域?
廣義的跨域:
(1) 資源跳轉:A鏈接、重定向、表單提交
(2) 資源嵌入:<link>
、<script>
、<img>
、<frame>
等dom標簽,還有樣式中background:url()
、@font-face()
等文件外鏈
(3) 腳本請求:js發起的ajax請求、dom和js對象的跨域操作等
其實我們通常所說的跨域是狹義的,是由瀏覽器同源策略限制的一類請求場景。
二.什么是瀏覽器跨域限制?本質是什么?
所謂瀏覽器跨域限制,其實是為了數據安全的考慮由Netscape提出來限制瀏覽器訪問跨域數據的策略。
這是一種約定,正式叫法為“瀏覽器同源策略”,目前已經在大多數瀏覽器中支持。
本質上,所謂瀏覽器同源策略,即:不允許瀏覽器訪問跨域的Cookie,ajax請求跨域接口等。
也就是說,凡是訪問與自己不在相同域的數據或接口時,瀏覽器都是不允許的。
最常見的例子:對於前后端完全分離的Web項目,前端頁面通過rest接口訪問數據時,會出現如下問題:
- 不允許發送POST請求:在發送POST請求之前會發送OPTIONS請求,HTTP響應狀態碼為403(Forbidden)。
- 允許發送GET請求:HTTP響應狀態碼為200,但是不能讀取服務器返回的數據。
同時,在瀏覽器(firefox調試)控制台可以看到如下提示:
已攔截跨源請求:同源策略禁止讀取位於 http://host:port/path 的遠程資源。(原因:CORS 頭缺少 'Access-Control-Allow-Origin')
。
對URL來說,所謂的“同源”包含3個要素:協議相同,主機名(域名或IP地址,IP地址則看做是根域名)相同,端口相同。
舉例來說,對於http://test.chench.org/page.html
這個地址,以下情況被認為是同源與不同源的:
URL | 結果 | 原因 | 說明 |
---|---|---|---|
http://test.chench.org/page2.html | 同源 | 協議相同,主機名相同,端口相同 | |
http://test.chench.org/dir2/page.html | 同源 | 協議相同,主機名相同,端口相同 | 相同域名下的不同目錄 |
http://102.12.34.123/page.html | 不同源 | 主機不同 | 域名與域名對應ip也不同源 |
http://test2.chench.org/page.html | 不同源 | 主域名相同,子域名不同 | |
http://chench.org/page.html | 不同源 | 域名不同 | 相同一級域名,不同二級域名 |
http://test.chench.org:81/page.html | 不同源 | 端口不同 | 相同域名,不同端口 |
https://test.chench.org/page.html | 不同源 | 協議不同 | 相同域名,不同協議 |
http://blog.icehoney.me/page.html | 不同源 | 主機不同 | 不同域名 |
## 三.為什么會存在瀏覽器跨域限制?
既然目前各主流瀏覽器都存在跨域限制,那么為什么一定要存在這個限制呢?如果沒有跨域限制會出現什么問題?
瀏覽器同源策略的提出本來就是為了避免數據安全的問題,即:限制來自不同源的“document”或腳本,對當前“document”讀取或設置某些屬性。
如果沒有這個限制,將會出現什么問題?不妨看一下幾個情形:
- 可能a.com的一段JavaScript腳本,在b.com未曾加載此腳本時,也可以隨意塗改b.com的頁面。
- 在瀏覽器中同時打開某電商網站(域名為b.com),同時在打開另一個網站(a.com),那么在a.com域名下的腳本可以讀取b.com下的Cookie,如果Cookie中包含隱私數據,后果不堪設想。
- 因為可以隨意讀取任意域名下的Cookie數據,很容易發起CSRF攻擊。
所以,同源策略是瀏覽器安全的基礎,同源策略一旦出現漏洞被繞過,也將帶來非常嚴重的后果,很多基於同源策略制定的安全方案都將失去效果。
## 四.對於瀏覽器來說,哪些資源(操作)會受到同源策略的限制?
對於瀏覽器來說,除了DOM,Cookie,XMLHttpRequest會受到同源策略的限制外,瀏覽器加載的一些第三方插件也有各自的同源策略。
最常見的一些插件如Flash,Java Applet,Silverlight,Google Gears等都有自己的控制策略。
另外,存儲在瀏覽器中的數據,如LocalStorage和IndexedDB,以源進行分割。每個源都擁有自己單獨的存儲空間,一個源中的Javascript腳本不能對屬於其它源的數據進行讀寫操作。
## 五.瀏覽器跨域限制會帶來什么問題?
隨着互聯網的發展,對用戶體驗的要求越來越高,AJAX應用也就越發頻繁,AJAX的本質就是XMLHttpRequest。
但XMLHttpRequest受到同源策略的約束,所以不能跨域訪問資源,這與我們的期望是相違背的。
## 六.解決瀏覽器跨域限制的方法有哪些?如何選擇合適的方案?
1. JSONP
在瀏覽器中,<script>
,<img>
,<iframe>
,<link>
等標簽都可以跨域加載資源,而不受同源策略的限制。
這些帶"src"屬性的標簽每次加載時,實際上是由瀏覽器發起了一次GET請求。
不同於XMLHttpRequest的是,通過src屬性加載的資源,瀏覽器限制了JavaScript的權限,使其不能讀寫返回的內容。
<script src="..."></script>
標簽嵌入跨域腳本。<link rel="stylesheet" href="...">
標簽嵌入CSS。由於CSS的松散的語法規則,CSS的跨域需要一個設置正確的Content-Type消息頭。不同瀏覽器有不同的限制。<img>
嵌入圖片。支持的圖片格式包括PNG,JPEG,GIF,BMP,SVG,...<video>
和<audio>
嵌入多媒體資源。<object>
,<embed>
和<applet>
的插件。@font-face
引入的字體。一些瀏覽器允許跨域字體(ross-origin fonts),一些需要同源字體(same-origin fonts)。<frame>
和<iframe>
載入的任何資源。站點可以使用X-Frame-Options消息頭來阻止這種形式的跨域交互。
JSONP就是利用這個特性,通過javascript標簽加載資源的方式請求跨域接口數據,間接繞開了瀏覽器同源策略的限制。
具體來說,就是在DOM中通過動態創建javascript標簽,並給標簽設置src屬性,在訪問請求參數中傳遞需要回調的函數名;
同時,服務端在響應jsonp請求時,將數據作為請求參數指定的客戶端回調函數參數作為返回值,這樣對於客戶端來說服務器的響應數據其實是回調函數的參數,是javascipt對象,而不是字符串,因此避免了使用JSON.parse的步驟。
2. CORS(Cross-Origin Resource Sharing)
CORS是一個解決瀏覽器跨域限制的W3C標准,全稱是"跨域資源共享"(Cross-origin resource sharing)。
它允許瀏覽器向跨域服務器發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。
具體來說,根據CORS標准定義,服務端需要在瀏覽器的跨域請求響應中包含指定消息頭,瀏覽器根據響應消息頭知道是否可以訪問跨域資源。
3. WebSocket
WebSocket是一種通信協議,使用ws://(非加密)和wss://(加密)作為協議前綴。
該協議不實行同源政策,只要服務器支持,就可以通過它進行跨源通信。
4. 解決方法總結
方案 | 優點 | 缺點 |
---|---|---|
JSONP | 簡單實用,老式瀏覽器全部支持,服務器改造非常小。 | 只支持GET請求,不支持POST等其他類型的HTTP請求,不能解決跨域頁面之間的javasript調用問題。 |
CORS | W3C標准,是跨源AJAX請求的根本解決方法,允許任何類型的請求。 | |
WebSocket | 不受瀏覽器同源策略影響 | 需要服務端支持協議,瀏覽器支持websocket,並非所有瀏覽器都支持websocket。 |
【參考】 https://github.com/acgotaku/WebSecurity/blob/master/docs/content/Browser_Security/Same-Origin-Policy.md 同源策略基本介紹 https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy 瀏覽器的同源策略 https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS HTTP access control (CORS) http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html 瀏覽器同源政策及其規避方法 https://www.zhihu.com/question/25427931 對於瀏覽器的同源策略你是怎樣理解的呢? http://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html#m1 JavaScript跨域總結與解決辦法 https://www.zhihu.com/question/26379635 為什么瀏覽器要限制跨域訪問?