關於瀏覽器跨域訪問(同源策略)
1. what
跨域是指從一個域名的網頁去訪問另一個域名的網頁。一個完整URL地址通常由 協議+主機+埠+路徑[+hash或search] 組成,其中hash和search是可選項、協議未列出則預設為http、port未列出則預設為80值。因此嚴格來說,兩個網頁地址的協議(http/https)、主機、埠三者任何一個不同就可以認為是跨域訪問,即使兩個地址是不同子域名也是跨域,如app.baidu.com與baidu.com。
2. why
瀏覽器出於安全考慮會限制跨域訪問(即同源策略),若不加限制則在一個站點上訪問後本地儲存的cookie等資訊在訪問第二個站點時就可能洩露了。(從這可見,跨域限制只是在通過瀏覽器訪問時才存在
沒有同源限制時的危害示例:
在瀏覽器上先登入股票網站www.stock.com,得到了cookie,以後再訪問stock時瀏覽器會自動帶上cookie;接著訪問惡意網站www.beautify.com,假定該網站頁面中包含一個惡意js指令碼,其行為是去訪問stock並把得到的資訊發到beautify網站,由於訪問stock時瀏覽器會自動帶上cookie故惡意指令碼可以成功竊取到資料。示意圖如下:
所幸瀏覽器有跨域訪問限制,故上述情況不會發生。
3. how
瀏覽器的同源限制是種傷敵一千自損八百的做法,如對於一個大系統來說有很多域名是正常的,同源限制使得同一系統內的不同域名下的服務無法互相訪問。
要突破瀏覽器跨域訪問的限制,本質上有兩種方法:
- 只需要讓不同地址對瀏覽器來說是同源的即可。如可以通過反向代理把需要互相訪問的地址放到反向代理後,這樣對瀏覽器來說就是同源的了。參考:通過Nginx反向代理實現跨域訪問-cnblogs
- 瀏覽器對具有src屬性的標籤(如script、img、iframe等)不做跨域限制,利用這些來實現跨域(即 jsonp)。原理:在頁面append一個script標籤,標籤地址為被跨域訪問站點地址,並在地址上加入自定義的回撥函式名引數,如?callback=myCallbackFunction,這裡的"callback"可以為其他,應事先商定好;被跨域站點的響應邏輯:若未檢查到"callback"引數則直接返回data,否則將data作為回撥函式名的引數一起返回,即 myCallbackFunction( data );瀏覽器script載入完後會執行myCallbackFunction函式,因此可以在myCallbackFunction裡對請求返回的data進行處理。參考:
第二種方法JSONP需要目標站點的配合,否則無法實現,第一種則不需要;
AJAX已經封裝支援了JSONP功能,但此時其和傳統意義上的AJAX請求是不一樣的,本質上是不同東西:ajax的核心是通過XmlHttpRequest獲取非本頁內容,而jsonp的核心則是動態新增<script>標籤來呼叫伺服器提供的js指令碼。更多參考:jsonp原理
思考:上一節中所述危害是以沒有同源限制為前提的,現實是瀏覽器都做了嚴格的同源限制,故該情況不會發生。然而在有同源限制下,我們仍可利用法2實現一個盜取使用者資訊的惡意指令碼:1、指令碼乾的事為讀取當前所在使用者站點的cookie等資訊,併發送到指令碼製作者的站點;2、傳送涉及到跨域,由於是“自己人”,可以選擇jsonp解決跨域;3、弄個惡意連結誘導使用者點選,從而將惡意指令碼載入到使用者站點,由於瀏覽器載入完script後就好執行,故done。