跨域
什么是跨域
瀏覽器為保證安全,增加的同源限制,其實請求是發出了,服務器也相應了,但是被瀏覽器劫持了。所謂同源是指,域名,協議,端口均相同,瀏覽器才會覺得符合要求。
一旦有一個不同源,瀏覽器便會觸發安全機制。
跨域解決辦法有哪些?
應該有很多,我就介紹JSONP, CORS, window.postMessage這三種理解的比較好的
-
JSONP
原理:
<script>
標簽不受跨域限制,ps:所有src屬性都不受同源限制,比如<img>
JSONP缺點: 只支持GET請求,不支持其他類型請求;優點:兼容性很好好,可以在古老的瀏覽器中運行。
-
CORS
CORS是一個W3C標准,全稱是"跨域資源共享"(Cross-origin resource sharing)。它允許瀏覽器向跨源服務器,發出XMLHttpRequest請求。
把請求分為了兩種:簡單請求和復雜請求。
如何分辨簡單請求和復雜請求呢?只要不符合下面條件,就是復雜請求。
- 請求方法是以下三種方法之一:
HEAD
GET
POST
- HTTP的頭信息不超出以下幾種字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain
知識點:
-
面對復雜請求,瀏覽器會在第一次先發送一個預檢請求,預檢請求使用的是OPTIONS方法,攜帶
Origin, Access-Control-Request-Method, Access-Control-Request-Headers
, - 服務器拒絕的話,返回也是正常http響應,只是沒有
Access-Control-Allow-Origin
字段; 服務器同意的話,返回的響應里除了Access-Control-Allow-Origin
,還會有
Access-Control-Allow-Methods, Access-Control-Allow-Headers, Access-Control-Allow-Credentials,//它的值是一個布爾值,表示是否允許發送Cookie。默認false,不發送 Access-Control-Max-Age // 該字段可選,用來指定本次預檢請求的有效期,單位為秒, 在此期間,不用發出另一條預檢請求。
- 一旦服務器通過了"預檢"請求,以后每次瀏覽器正常的CORS請求,就都跟簡單請求一樣,會有一個Origin頭信息字段。服務器的回應,也都會有一個Access-Control-Allow-Origin頭信息字段。
-
HTML5 window.postMessage API
window.postMessage是一個安全的,基於事件的消息API
- 發送消息
需要發送的窗口winA,調用postMessage方法,即可發送消息,其中winA還可以是文檔窗口中的iframe:
var iframe = document.getElementById('my-iframe'); var win = iframe.documentWindow;
postMessage語法:otherWindow.postMessage(message, targetOrigin, [transfer]);
舉栗子:win.postMessage('Hello', 'ttp://jhssdemo.duapp.com/');
- 接收消息
要想接收到之前源窗口通過postMessage發出的消息,只需要在目標窗口注冊message事件並綁定事件監聽函數,就可以在函數參數中獲取消息。
注意:postMessage只能發送字符串信息。
window.onload = function() { var text = document.getElementById('txt'); function receiveMsg(e) { // e 有三個屬性:data, origin, source console.log("Got a message!"); console.log("\nMessage: " + e.data); console.log("\nOrigin: " + e.origin); // console.log("Source: " + e.source); text.innerHTML = "Got a message!<br>" + "Message: " + e.data + "<br>Origin: " + e.origin; } if (window.addEventListener) { //為窗口注冊message事件,並綁定監聽函數 window.addEventListener('message', receiveMsg, false); }else { window.attachEvent('message', receiveMsg); } };