XMLHttpRequest的跨域請求

來源:互聯網
上載者:User

標籤:目錄   apn   exp   oql   false   rc4   gid   doc   mtd   

緣起

由於瀏覽器的同源策略,非同源不可請求。

但是,在實踐當中,經常會出現需要跨域請求資源的情況,比較典型的例如某個子網域名稱向負責進行使用者驗證的子網域名稱請求使用者資訊等應用。

以前要實現跨域訪問,可以通過JSONP、Flash或者伺服器中轉的方式來實現,但是現在我們有了CORS。

CORS與JSONP相比,無疑更為先進、方便和可靠。

123 1、 JSONP只能實現GET請求,而CORS支援所有類型的HTTP請求。2、 使用CORS,開發人員可以使用普通的XMLHttpRequest發起請求和獲得資料,比起JSONP有更好的錯誤處理。3、 JSONP主要被老的瀏覽器支援,它們往往不支援CORS,而絕大多數現代瀏覽器都已經支援了CORS
JSONP的最基本的原理

動態添加一個<script>標籤,而script標籤的src屬性是沒有跨域的限制的。這樣說來,這種跨域方式其實與ajax XmlHttpRequest協議無關了。

這樣其實"jQuery AJAX跨域問題"就成了個偽命題,jquery $.ajax方法名有誤導人之嫌。

如果設為dataType: ‘jsonp‘,這個$.ajax方法就和ajax XmlHttpRequest沒什麼關係了,取而代之的則是JSONP協議。JSONP是一個非官方的協議,它允許在伺服器端整合Script tags返回至用戶端,通過javascript callback的形式實現跨域訪問。

JSONP即JSON with Padding。由於同源策略的限制,XmlHttpRequest只允許請求當前源(網域名稱、協議、連接埠)的資源。如果要進行跨域請求, 我們可以通過使用html的script標記來進行跨域請求,並在響應中返回要執行的script代碼,其中可以直接使用JSON傳遞 javascript對象。 這種跨域的通訊方式稱為JSONP。

Cross-Origin Resource sharing

這是W3C  新出的一個標準,簡單的講就是通過伺服器/用戶端 一些Headers的設定及確認 來實現跨域請求,這些包頭有

  Cross-Origin Resource sharing

這是W3C  新出的一個標準,簡單的講就是通過伺服器/用戶端 一些Headers的設定及確認 來實現跨域請求,這些包頭有

 Syntax

  1. 5.1 Access-Control-Allow-Origin Response Header
  2. 5.2 Access-Control-Allow-Credentials Response Header
  3. 5.3 Access-Control-Expose-Headers Response Header
  4. 5.4 Access-Control-Max-Age Response Header
  5. 5.5 Access-Control-Allow-Methods Response Header
  6. 5.6 Access-Control-Allow-Headers Response Header
  7. 5.7 Origin Request Header
  8. 5.8 Access-Control-Request-Method Request Header
  9. 5.9 Access-Control-Request-Headers Request Header

   例如

  • Access-Control-Allow-Origin: http://www.test.com
  • Access-Control-Allow-Methods: POST, GET, OPTIONS  
  • Access-Control-Allow-Headers: POWERED-BY-MENGXIANHUI  
  • Access-Control-Max-Age: 30

可以參考 http://www.w3.org/TR/access-control/#access-control-allow-origin-response-header  w3c的網站

1234567 Access-Control-Allow-Origin: 允許跨域訪問的域,可以是一個域的列表,也可以是萬用字元"*"。這裡要注意Origin規則只對網域名稱有效,並不會對子目錄有效。即http://www.test/test/是無效的。但是不同子網域名稱需要分開設定,這裡的規則可以參照那篇同源策略Access-Control-Allow-Credentials: 是否允許請求帶有驗證資訊,這部分將會在下面詳細解釋Access-Control-Expose-Headers: 允許指令碼訪問的返回頭,請求成功後,指令碼可以在XMLHttpRequest中訪問這些頭的資訊(貌似webkit沒有實現這個)Access-Control-Max-Age: 緩衝此次請求的秒數。在這個時間範圍內,所有同類型的請求都將不再發送預檢請求而是直接使用此次返回的頭作為判斷依據,非常有用,大幅最佳化請求次數Access-Control-Allow-Methods: 允許使用的要求方法,以逗號隔開Access-Control-Allow-Headers: 允許自訂的頭部,以逗號隔開,大小寫不敏感

Access-Control-Allow-Credentials

在跨域請求中,預設情況下,HTTP Authentication資訊,Cookie頭以及使用者的SSL認證無論在預檢請求中或是在實際請求都是不會被發送的。

但是,通過設定XMLHttpRequest的credentials為true,就會啟用認證資訊機制。

雖然簡單請求還是不需要發送預檢請求,但是此時判斷請求是否成功需要額外判斷Access-Control-Allow-Credentials,如果Access-Control-Allow-Credentials為false,請求失敗。

十分需要注意的的一點就是此時Access-Control-Allow-Origin不能為萬用字元"*"(真是便宜了一幫偷懶的程式員),如果Access-Control-Allow-Origin是萬用字元"*"的話,仍將認為請求失敗

即便是失敗的請求,如果返回頭中有Set-Cookie的頭,瀏覽器還是會照常設定Cookie

用戶端頁面test.php

1234567891011121314151617181920212223242526272829 <!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"<head> <title>crossDomainRequest</title> </head> <body> <input type=‘button‘ value=‘開始測試‘ onclick="crossDomainRequest()"  /> <div id="content"></div> <script type="text/javascript">function createXHR(){    return window.XMLHttpRequest?    new XMLHttpRequest():    new ActiveXObject("Microsoft.XMLHTTP");}function getappkey(url){    xmlHttp = createXHR();    xmlHttp.open("GET",url,false);    xmlHttp.send();    result = xmlHttp.responseText;    return result;}function crossDomainRequest(){    var content =getappkey(‘http://127.0.0.10/gettest.php‘);    document.getElementById("content").innerHTML=content;}</script> </body> </html> 

服務端頁面gettest.php

1234 <?phpheader("Access-Control-Allow-Origin:  http://127.0.0.1");echo "test success!";?>

 

 

如果不允許的話

 

 

所以跨域有以下幾種方法

通過webserver【nginx】配置來跨域
123456789101112131415161718192021222324252627282930313233343536 ## Wide-open CORS config for nginx#location / {     if ($request_method = ‘OPTIONS‘) {        add_header ‘Access-Control-Allow-Origin‘ ‘*‘;        #        # Om nom nom cookies        #        add_header ‘Access-Control-Allow-Credentials‘ ‘true‘;        add_header ‘Access-Control-Allow-Methods‘ ‘GET, POST, OPTIONS‘;        #        # Custom headers and headers various browsers *should* be OK with but aren‘t        #        add_header ‘Access-Control-Allow-Headers‘ ‘DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type‘;        #        # Tell client that this pre-flight info is valid for 20 days        #        add_header ‘Access-Control-Max-Age‘ 1728000;        add_header ‘Content-Type‘ ‘text/plain charset=UTF-8‘;        add_header ‘Content-Length‘ 0;        return 204;     }     if ($request_method = ‘POST‘) {        add_header ‘Access-Control-Allow-Origin‘ ‘*‘;        add_header ‘Access-Control-Allow-Credentials‘ ‘true‘;        add_header ‘Access-Control-Allow-Methods‘ ‘GET, POST, OPTIONS‘;        add_header ‘Access-Control-Allow-Headers‘ ‘DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type‘;     }     if ($request_method = ‘GET‘) {        add_header ‘Access-Control-Allow-Origin‘ ‘*‘;        add_header ‘Access-Control-Allow-Credentials‘ ‘true‘;        add_header ‘Access-Control-Allow-Methods‘ ‘GET, POST, OPTIONS‘;        add_header ‘Access-Control-Allow-Headers‘ ‘DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type‘;     }}

範例程式碼

12345678910 location /{add_header ‘Access-Control-Allow-Origin‘ ‘http://www.test.com‘;add_header ‘Access-Control-Allow-Credentials‘ ‘true‘;add_header ‘Access-Control-Allow-Methods‘ ‘GET‘;  ......  }

第一條指令:授權從http://www.test.com的請求

第二條指令:當該標誌為真時,響應於該請求是否可以被暴露

第三天指令:指定請求的方法,可以是GET,POST等

如果需要允許來自任何域的訪問,可以這樣配置

1 Access-Control-Allow-Origin: *
通過後端程式來跨域
1234567891011121314151617181920 <?phpheader("Access-Control-Allow-Origin:http://www.test.com");header("Access-Control-Allow-Origin:*");echo json_encode($_POST);?><script type="text/javascript">$("#ajax").click(function(){    $.ajax({        type: "POST",        url: "http://www.test.com/test2.php",        data: ‘name=test‘,        dataType:"json",        success: function(data){            $(‘#Result‘).text(data.name);        }    });});</script>
JSONP
1234567891011121314151617181920212223242526 <?phpif(isset($_GET[‘name‘]) && isset($_GET[‘callback‘]))  //callback根js端要對應,不然會報錯的{    echo $_GET[‘callback‘]. ‘(‘ . json_encode($_GET) . ‘);}?><script type="text/javascript">$("#jsonp").click(function(){    $.ajax({            url: ‘http://www.test.com/test1.php‘,            data: {name: ‘jsonp‘},            dataType: ‘jsonp‘,            jsonp: ‘callback‘,      //為服務端準備的參數            jsonpCallback: ‘getdata‘,   //回呼函數            success: function(){                alert("success");            }    });});function getdata(data){    $(‘#Result‘).text(data.name);}</script>
getJSON
12345678 <script type="text/javascript">$("#getjson").click(function(){    $.getJSON(‘http://www.test.com/test1.php?name=getjson&callback=?‘function(data){    //沒有回呼函數,直接處理        $(‘#Result‘).text(data.name);    })})</script>
getScript
12345 <script type="text/javascript">$("#getscript").click(function(){    $.getScript(‘http://www.test.com/test1.php?name=getscript&callback=getdata‘);});</script>

 

XMLHttpRequest的跨域請求

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.