1. 程式人生 > >一文梳理同源策略與跨域技術

一文梳理同源策略與跨域技術

### 1.同源策略 > 同源策略是一個重要的安全策略,它用於限制一個origin的文件或者它載入的指令碼如何能與另一個源的資源進行互動。它能幫助阻隔惡意文件,減少可能被攻擊的媒介。 **1.1何謂同源**? 如果兩個 URL 的 [protocol](https://developer.mozilla.org/zh-CN/docs/Glossary/Protocol)、[port](https://developer.mozilla.org/en-US/docs/Glossary/port) (如果有指定的話)和 [host](https://developer.mozilla.org/en-US/docs/Glossary/host) 都相同的話,則這兩個 URL 是*同源*。這個方案也被稱為“協議/主機/埠元組”,或者直接是 “元組”。 下表給出了與 URL `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` | 失敗 | 協議不同 | | `http://store.company.com:81/dir/etc.html` | 失敗 | 埠不同 ( `http://` 預設埠是80) | | `http://news.company.com/dir/other.html` | 失敗 | 主機不同 | 隨著網際網路的發展,"同源政策"越來越嚴格。目前,如果非同源,共有三種行為受到限制。 > (1) Cookie、LocalStorage 和 IndexDB 無法讀取。 > > (2) DOM 無法獲得。 > > (3) AJAX 請求不能傳送。 雖然這些限制是必要的,但是有時很不方便,合理的用途也受到影響。 ### 2.跨域 #### 2.1 何謂跨域? > **跨域問題是由於瀏覽器為了防止CSRF(跨站請求偽造)攻擊,避免惡意攻擊而帶來的風險而採取的同源策略限制。當一個頁面中使用XMLHTTPRequest物件傳送HTTP請求時(XHR請求),必須保證當前頁面和請求的物件是同源的** 能實現跨域的技術還是比較多的,篇幅有限,這篇文章主要給大家帶來: - JSONP跨域 - CORS跨域 - postmessage - 伺服器代理 - WebSocket #### 2.2 JSONP跨域 **JSONP的原理:靜態資源請求不受同源策略影響**。具體:瀏覽器只對XHR(XMLHttpRequest)請求有同源請求限制,而對script標籤src屬性、link標籤ref屬性和img標籤src屬性沒有這種限制,利用這個“漏洞”就可以很好的解決跨域請求. **JSONP 由兩部分組成:回撥函式和資料**。回撥函式是當響應到來時應該在頁面中呼叫的函式。回撥 函式的名字一般是在請求中指定的。而資料就是傳入回撥函式中的JSON資料。 ```javascrip ``` JSONP 是通過動態`複製程式碼 ``` 後端部分 ``` const WebSocket = require("ws");const server = new WebSocket.Server({ port: 8080 });server.on("connection", function(socket) { socket.on("message", function(data) { socket.send(data); });}); ``` **總結**: - 建立在 TCP 協議之上,伺服器端的實現比較容易。 - 與 HTTP 協議有著良好的相容性。預設埠也是80和443,並且握手階段採用 HTTP 協議,因此握手時不容易遮蔽,能通過各種 HTTP 代理伺服器。 - 資料格式比較輕量,效能開銷小,通訊高效。 - 可以傳送文字,也可以傳送二進位制資料。 - 沒有同源限制,客戶端可以與任意伺服器通訊。 - 協議識別符號是`ws`(如果加密,則為`wss`),伺服器網址就是 URL。 #### 2.6 Nginx反向代理 這裡需要說明的是: **跨域是瀏覽器行為,不是伺服器行為。同源策略僅是針對瀏覽器的安全策略**。伺服器端呼叫HTTP介面只是使用HTTP協議,不需要同源策略,也就不存在跨域問題。 實際上,請求已經到達伺服器了,只不過在回來的時候被瀏覽器限制了 **實現思路:**通過Nginx配置一個代理伺服器域名與發出請求域名相同,埠不同,反向代理訪問目標域名。 背景:domain1需要跨域訪問domain2 ``` server { listen 80; server_name www.domain1.com; location / { proxy_pass www.domain2.com:8080; } } ``` 需要說明的是,前端跨域的技術還有許多,只是限於篇幅沒有講到,比如node正向代理,window.name+iframe等。還想了解別的跨域方案的小夥伴可以看本文的參考文章去觀摩觀摩。 ### 小結 同源策略僅僅是針對瀏覽器的安全策略,跨域是瀏覽器行為,如果兩個 URL 的 [protocol](https://developer.mozilla.org/zh-CN/docs/Glossary/Protocol)、[port](https://developer.mozilla.org/en-US/docs/Glossary/port) (如果有指定的話)和 [host](https://developer.mozilla.org/en-US/docs/Glossary/host) 都相同的話,則這兩個 URL 是*同源*。現在有許多的跨域方案可供大家選擇,本文僅僅選擇了JSONP、CORS、postMessage等6種跨域技術進行了闡述,希望能在梳理自己知識點的同時幫助到一些人。 **參考文章:** [jsonp完美解決跨域問題,簡單](https://blog.csdn.net/jayLog/article/details/104274132) [跨域解決方案實踐cors及jsonp](https://juejin.im/entry/5b3a2775f265da630e27a7ce) [跨資源共享cors詳解-阮一峰](http://www.ruanyifeng.com/blog/2016/04/cors.html) [瀏覽器同源政策及其規避方法-阮一峰](http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html) [postmessage濫用導致的安全問題](https://p0sec.net/index.php/archives/124/) [10種跨域解決方案(附終極大招)](https://juejin.im/post/5e948bbbf265da47f2561705#heading-33) [websocket教程-阮一峰](http://www.ruanyifeng.com/blog/2017/05/websocket.html) [9種常見的前端跨域解決方案](https://zhuanlan.zhihu.com/p/8