跨域請求的經常使用方式及解釋

同源策略

首先基於安全的緣由,瀏覽器是存在同源策略這個機制的,同源策略阻止從一個域加載的腳本去獲取另外一個域上的文檔屬性。也就是說,受到請求的 URL 的域必須與當前 Web 頁面的域相同。這意味着瀏覽器隔離來自不一樣源的內容,以防止它們之間的操做。html

js跨域是指經過js在不一樣的域之間進行數據傳輸或通訊,好比用ajax向一個不一樣的域請求數據,或者經過js獲取頁面中不一樣域的框架中(iframe)的數據。前端

只要協議、域名、端口有任何一個不一樣,都被看成是不一樣的域。html5

 

下面介紹幾種經常使用的跨域請求方式

默認端口爲:8080jquery

1、利用jQuery獲取jsonp

JSONP的原理與實現思路

1)Web頁面調用js文件,可跨域。擴展:但凡是有src屬性的標籤都具備跨域能力。
2)跨域服務器 動態生成數據 並存入js文件(一般json後綴),供客戶端調用。
3)爲了便於客戶端使用數據,造成一個非正式傳輸協議,稱爲JSONP。該協議重點是容許用戶傳遞一個callback參數給服務器,而後服務器返回數據時 將此callback參數做爲函數名包裹住JSON數據,使得客戶端能夠隨意定製本身的函數來自動處理返回數據。ajax

 

 1.1若是咱們不用跨域請求的寫法的話:json

$('#cors1').click(function () {
    $.ajax({
        type:'get',
        url:'http://localhost:8081/girl/hello/say',
        success:function (data) {
            console.log(data);
        }
    })
});

1.2使用跨越請求的寫法,最簡單的就是設置dataType:jsonp:後端

jsonp指定服務器返回的數據類型爲jsonp格式,能夠看發起的請求路徑,自動帶了一個callback=xxx,xxx是jquery隨機生成的一個回調函數名稱。跨域

這裏的success默認success()做爲回調函數。數據返回到前端後,就是success(result)的形式,由於是script腳本,因此自動調用success函數,而result就是success的參數。瀏覽器

$('#cors1').click(function () {
    $.ajax({
        type:'get',
        dataType: 'jsonp',
        url:'http://localhost:8081/girl/hello/say',
        success:function (data) {
            console.log(data);
        }
    })
});
    @RequestMapping(value="/say", method = RequestMethod.GET)      //後端代碼
    public String say(@RequestParam("callback") String callback){

        //callback前端傳過來的回調函數名稱

        //數據
        String result = "{age:22}";
        
        //用回調函數名稱包裹返回數據,這樣,返回數據就做爲回調函數的參數傳回去了
        result = callback + "(" + result + ")";
        return result;
        
    }

 

1.3jsonpCallback

爲jsonp請求指定一個回調函數名。這個值將用來取代jQuery自動生成的隨機函數名。安全

調用回調函數的時候,先調用了指定的showData,而後再調用了success。

$('#cors1').click(function () {
    $.ajax({
        type:'get',
        dataType: 'jsonp',   //指定服務器返回的數據類型 
        jsonpCallback: 'showData',    //指定回調函數名稱
        url:'http://localhost:8081/girl/hello/say',
        success:function (data) {
            console.log(data);
        }
    })
});

function showData(data) {
    console.log("show"+data);
}

1.4jsonp

在一個jsonp請求中重寫回調函數的名字。這個值用來替代在"callback=?"這種GET或POST請求中URL參數裏的"callback"部分,好比{jsonp:'onJsonPLoad'}會致使將"onJsonPLoad=?"傳給服務器。

$('#cors1').click(function () {
    $.ajax({
        type:'get',
        dataType: 'jsonp',
        jsonpCallback: 'showData',
        jsonp: 'sendParam',  //指定參數名稱
        url:'http://localhost:8081/girl/hello/say',
        success:function (data) {
            console.log(data);
        }
    })
});

function showData(data) {
    console.log(data);
}

指定jsonp後,後端也要改變:

    @RequestMapping(value="/say", method = RequestMethod.GET)
    public String say(@RequestParam("sendParam") String sendParam){

        //sendParam前端傳過來的回調函數名稱

        //數據
        String result = "{age:22}";

        //用回調函數名稱包裹返回數據,這樣,返回數據就做爲回調函數的參數傳回去了
        result = sendParam + "(" + result + ")";
        return result;

    }

 

 

1.5jsonp方式不支持POST方式跨域請求,就算指定成POST方式,會自動轉爲GET方式;然後端若是設置成POST方式了,那就請求不了了。

 

2、設置CORS頭「Access-Control-Allow-Origin」

  •  CORS的原理:
     CORS定義一種跨域訪問的機制,可讓AJAX實現跨域訪問。CORS 容許一個域上的網絡應用向另外一個域提交跨域 AJAX 請求。實現此功能很是簡單,只需由服務器發送一個響應標頭便可。
 
$('#cors1').click(function () {
    $.ajax({
        type:'get',
        url:'http://localhost:8081/girl/hello/say',
        success:function (data) {
            console.log(data);
        }
    })
});
    @RequestMapping(value="/say", method = RequestMethod.GET)
    public String say(HttpServletRequest request, HttpServletResponse response){
        //設置響應頭
        response.setHeader("Access-Control-Allow-Origin","*");  //當前我設置的header爲「*」,任意一個請求過來以後服務端咱們均可以進行處理&響應
    // 指定特定域名能夠訪問
       response.setHeader("Access-Control-Allow-Origin", "http:localhost:8080/")
//數據
        String result = "{age:22}";
        return result;
    }

 

 

3、iframe+window.postMessage實現跨域

script、image、iframe的src都不受同源策略的影響。因此咱們能夠藉助這一特色,實現跨域。

postMessage()方法容許來自不一樣源的腳本採用異步方式進行有限的通訊,能夠實現跨文本檔、多窗口、跨域消息傳遞。

 

發送消息

postMessage(data,origin)方法接受兩個參數

 1.data:要傳遞的數據,html5規範中提到該參數能夠是JavaScript的任意基本類型或可複製的對象,然而並非全部瀏覽器都作到了這點兒,部分瀏覽器只能處理字符串參數,因此咱們在傳遞參數的時候須要使用JSON.stringify()方法對對象參數序列化,在低版本IE中引用json2.js能夠實現相似效果。

2.origin:字符串參數,指明目標窗口的源,協議+主機+端口號[+URL],URL會被忽略,因此能夠不寫,這個參數是爲了安全考慮,postMessage()方法只會將message傳遞給指定窗口,固然若是願意也能夠建參數設置爲"*",這樣能夠傳遞給任意窗口,若是要指定和當前窗口同源的話設置爲"/"。

<iframe id="ifr" src="http://localhost:8081/girl/b.html"></iframe>
window.onload = function () {
    var ifr = document.getElementById("ifr");
    ifr.contentWindow.postMessage("crsf","http://localhost:8081");
};

接收消息

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>testb</title>
</head>
<body>
    <div>b</div>
</body>
</html>
<script>
window.addEventListener('message', function(event){
console.log('origin: '+event.origin);    //origin: http://localhost:8080
console.log('data: '+event.data);      //data: crsf
console.log(event.source);
// 回發數據
event.source.postMessage('hello world', event.origin);
});
</script>

有幾個重要屬性

  1. origin:發送消息窗口的源(協議+主機+端口號)
  2. data:顧名思義,是傳遞來的message
  3. source:發送消息的窗口對象

這樣就能夠接收跨域的消息了,咱們還能夠發送消息回去。

相關文章
相關標籤/搜索