跨域解決方法,jsonp和cors的優劣性

原文鏈接:https://www.jianshu.com/p/f880878c1398

跨域解決方法

雖然在安全層面上同源限制是必要的,但有時同源策略會對我們的合理用途造成影響,爲了避免開發的應用受到限制,有多種方式可以繞開同源策略,下面介紹的是經常使用的 JSONP, CORS 方法。

JSONP

原理:

  • JSONP 是一種非官方的跨域數據交互協議
  • JSONP 本質上是利用 <script><img><iframe> 等標籤不受同源策略限制,可以從不同域加載並執行資源的特性,來實現數據跨域傳輸。
  • JSONP由兩部分組成:回調函數和數據。回調函數是當響應到來時應該在頁面中調用的函數,而數據就是傳入回調函數中的JSON數據。
  • JSONP 的理念就是,與服務端約定好一個回調函數名,服務端接收到請求後,將返回一段 Javascript,在這段 Javascript 代碼中調用了約定好的回調函數,並且將數據作爲參數進行傳遞。當網頁接收到這段 Javascript 代碼後,就會執行這個回調函數,這時數據已經成功傳輸到客戶端了。

示例:

首先當前頁面中聲明有這樣的一個函數,它將作爲 JSONP 的回調函數處理作爲函數參數傳入的數據

<script type="text/javascript">
    function dosomething(jsondata){
        //處理獲得的json數據
    }
</script>

然後,我們就可以藉助 <script><img><iframe> 等標籤可以引入不同域資源的特性,將需要發送的請求的路徑作爲src參數,其中需要注意的是:需要告知服務端回調函數的函數名。

<script src="http://example.com/data.php?callback=dosomething"></script>

這時服務端在返回數據的時候,就會返回一端 Javascript 代碼,在 Javascript代碼中調用了回調函數,並且需要返回的數據作爲回調函數的參數

dosomething(['a','b','c']);

最後頁面成功加載了剛纔指定路徑的資源後,將會執行該 Javascript 代碼,dosomething函數將執行,這時一次跨域請求完成。

另外,如果頁面引入了 jQuery,那麼可以通過它封裝的方法很方便的實現JSONP操作了

// Using YQL and JSONP
$.ajax({
    url: "http://query.yahooapis.com/v1/public/yql",
 
    // The name of the callback parameter, as specified by the YQL service
    jsonp: "callback",
 
    // Tell jQuery we're expecting JSONP
    dataType: "jsonp",
 
    // Tell YQL what we want and that we want JSON
    data: {
        q: "select title,abstract,url from search.news where query=\"cat\"",
        format: "json"
    },
 
    // Work with the response
    success: function( response ) {
        console.log( response ); // server response
    }
});

優缺點:

JSONP 的優點是:它不像XMLHttpRequest對象實現的Ajax請求那樣受到同源策略的限制;它的兼容性更好,在更加古老的瀏覽器中都可以運行。

JSONP 的缺點是:它只支持 GET 請求,而不支持 POST 請求等其他類型的 HTTP 請求

CORS

介紹

​ 跨源資源共享 Cross-Origin Resource Sharing(CORS) 是一個新的 W3C 標準,它新增的一組HTTP首部字段,允許服務端其聲明哪些源站有權限訪問哪些資源。換言之,它允許瀏覽器向聲明瞭 CORS 的跨域服務器,發出 XMLHttpReuest 請求,從而克服 Ajax 只能同源使用的限制。

​ 另外,規範也要求對於非簡單請求,瀏覽器必須首先使用 OPTION 方法發起一個預檢請求(preflight request),從而獲知服務端是否允許該跨域請求,在服務器確定允許後,才發起實際的HTTP請求。對於簡單請求、非簡單請求以及預檢請求的詳細資料可以閱讀HTTP訪問控制(CORS)

HTTP 協議 Header 簡析

下面對 CORS 中新增的 HTTP 首部字段進行簡析:

  • Access-Control-Allow-Origin

    響應首部中可以攜帶這個頭部表示服務器允許哪些域可以訪問該資源,其語法如下:

    Access-Control-Allow-Origin: <origin> | *
    

    其中,origin 參數的值指定了允許訪問該資源的外域 URI。對於不需要攜帶身份憑證的請求,服務器可以指定該字段的值爲通配符,表示允許來自所有域的請求。

  • Access-Control-Allow-Methods

    該首部字段用於預檢請求的響應,指明實際請求所允許使用的HTTP方法。其語法如下:

    Access-Control-Allow-Methods: <method>[, <method>]*
    
  • Access-Control-Allow-Headers

    該首部字段用於預檢請求的響應。指明瞭實際請求中允許攜帶的首部字段。其語法如下:

    Access-Control-Allow-Headers: <field-name>[, <field-name>]*
    
  • Access-Control-Max-Age

    該首部字段用於預檢請求的響應,指定了預檢請求能夠被緩存多久,其語法如下:

    Access-Control-Max-Age: <delta-seconds>
    
  • Access-Control-Allow-Credentials

    該字段可選。它的值是一個布爾值,表示是否允許發送Cookie。默認情況下,Cookie不包括在CORS請求之中。設爲true,即表示服務器明確許可,Cookie可以包含在請求中,一起發給服務器。其語法如下:

    Access-Control-Allow-Credentials: true
    

    另外,如果要把 Cookie 發送到服務器,除了服務端要帶上Access-Control-Allow-Credentials首部字段外,另一方面請求中也要帶上withCredentials屬性。

    但是需要注意的是:如果需要在 Ajax 中設置和獲取 Cookie,那麼Access-Control-Allow-Origin首部字段不能設置爲* ,必須設置爲具體的 origin 源站。詳細可閱讀文章CORS 跨域 Cookie 的設置與獲取

  • Origin

    該首部字段表明預檢請求或實際請求的源站。不管是否爲跨域請求,Origin字段總是被髮送。其語法如下:

    Origin: <origin>
    
  • Access-Control-Request-Method

    該首部字段用於預檢請求。其作用是,將實際請求所使用的 HTTP 方法告訴服務器。其語法如下:

    Access-Control-Request-Method: <method>
    
  • Access-Control-Request-Headers

    該首部字段用於預檢請求。其作用是,將實際請求所攜帶的首部字段告訴服務器。其語法如下:

    Access-Control-Request-Headers: <field-name>[, <field-name>]*
    

示例

假設我們在 bbb.cn 域名下,發送一個 Ajax 請求到 aaa.cn 域名,其路徑如下:http://aaa.cn/localserver/api/corsTest 。由於同源策略,這樣的 Ajax 請求將會被瀏覽器所攔截,得到下面的信息:

若想能夠發送跨域請求,我們只需要在服務器的響應中配置適當的CORS HTTP 首部字段就可以了,例如可以加入以下的首部字段:

Access-Control-Allow-Methods:*

此時,Ajax請求就可以順利的發送和接收了,對應的請求和響應頭部如下:

對於在 Java Web 項目中,如何在 Servlet 或這 Spring MVC 中配置 CORS 可以閱讀文章Spring MVC 實現 CORS 跨域

與 JSONP 的比較

  • JSONP 只能實現 GET 請求,而 CORS 支持所有類型的 HTTP 請求
  • 使用 CORS ,開發者可以是使用普通的 XMLHttpRequest 發起請求和獲取數據,比起 JSONP 有更好的錯誤處理
  • 雖然絕大多數現代的瀏覽器都已經支持 CORS,但是 CORS 的兼容性比不上 JSONP,一些比較老的瀏覽器只支持 JSONP



作者:ken_ljq
鏈接:https://www.jianshu.com/p/f880878c1398
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯繫作者獲得授權並註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章