一,啥是跨域
同源策略是瀏覽器最基本的安全功能。
通常域名是由以下幾部分組成:
http:// www.baidu.com : 8080 / #abc
協議 域名 端口號 hash、查詢字符串、文件名等
同源策略會限制以下的內容:
1,cookie、localstorage和indexDB無法讀取
2,DOM無法獲得
3,ajax發送后會被瀏覽器攔截
不過有些標簽是可以允許跨域加載的:
1,img 標簽
2,link 標簽
3,script 文件
當協議、域名、端口號任意一個不相同時,都算作不同域。不同域之間請求資源,就是跨域。
如果是協議和端口號造成的跨域,前端是無法解決的。
在跨域的問題上,是通過 ‘url首部’來識別而不會根據域名對應的ip地址是否相同來判斷。 url首部可以理解為‘協議、域名和端口必須匹配’。
跨域並不是http請求發送不出去,請求可以發出去,服務端也能接受並正常返回結果,只是結果被瀏覽器攔截了。
因為跨域本身是為了阻止用戶獲取不同域下的內容。所以表單提交這種方式是可以發起跨域請求的,因為表單只會提交不會獲取新內容。
二, 跨域方法
1,jsonp
因為在頁面上調用script標簽沒有跨域的限制(不僅如此,凡是擁有src屬性的標簽都具有跨域的能力)。
首先在本頁面聲明一個用來獲取數據的回調函數, 創建一個script標簽,將要跨域的地址加上該回調函數賦值給script的src屬性(通過 ?callback= fn)
服務器接收到該請求后,會在返回的文件中 將該回調函數名和數據拼接起來,返回給客戶端。客戶端執行該回調函數,就可以獲取到服務端傳過來的數據。
jsonp的兼容性很好,但是僅僅只支持get請求。
2,cors
cors需要瀏覽器和后台同時支持。 ie8和ie9需要通過XDomainRequest實現
瀏覽器會自動進行cors通信,所以只要后台實現了cros,就實現了跨域。
服務端設置Access-Control-Allow-Origin就可以開啟cors,該屬性表示哪些域名可以訪問資源。
在使用cors發送請求時,會出現兩種情況:
簡單請求:
只要同時滿足以下兩種條件就屬於簡單請求
條件1: 使用get 、head、post方法
條件2: content-type的值為 text/plain、 multipart/form-data、 application/x-www-form-urlencoded 三者之一。
復雜請求:
不符合簡單請求的就屬於復雜請求。 復雜請求的cors會在正式請求之前增加一次http查詢請求(預檢請求),該請求是option方法,通過該請求來知道服務端是否允許跨域請求。
3,postMessage
XMLHttpRequest Level 2的api,可以解決以下的問題:
頁面和其打開的新窗口的數據傳遞
多窗口之間消息傳遞
頁面和嵌套的iframe消息傳遞
以上三個場景的跨域數據傳遞
postMessage方法允許來自不同源的腳本采用異步方式進行有限的通信。
otherWindow.postMessage(message,targetOrigin,[transfer]);
message: 要發送的數據
targetOrigin:通過窗口的origin屬性來指定哪些窗口能接收到消息,只有目標窗口的協議、域名和端口都和提供的targetOrigin匹配的時候,才會被發送。
transfer: 和message同時傳遞的Transferable對象,這些對象的所有權將被轉移給消息的接收方,發送方不再保有所有權。
4,websocket
h5的一個持久化協議。實現了瀏覽器和服務器的全雙工通信,同時也是跨域的一種解決方案。
websocket和http都是應用層協議,都基於TCP。但是websocket是一種雙向通信協議,一旦連接建立,服務端和客戶端都可以向對方發送或接收數據。
websocket建立的時候需要用到http協議,建立好連接之后就與http無關了。
5,Node js中間件代理
同源策略是瀏覽器需要遵循的標准,而如果服務端向服務端請求就無需遵循同源策略。
代理服務器接收瀏覽器的請求,處理后轉發給服務器,收到服務器的響應后再轉發給瀏覽器。
需要注意的是代理服務器和瀏覽器之間也遵循同源策略。
6,nginx反向代理
類似node中間件代理,需要搭建一個中轉nginx服務器,用於轉發請求。
最簡單的跨域方式。只要修改nginx的配置即可解決跨域問題。
還有一些不常用的奇淫技巧,就不寫了。 一般用的最多的就是cors和nginx反向代理。