ajax跨域問題處理


這段時間面試 經常會問到這個問題。也就是說,如果你的前端想要獲取其他域名下的數據,前端需要如何請求,后端需要如何設置。

最常見的處理方式有兩種

方法一,在java代碼中設置response.setHeader("Access-Control-Allow-Origin","*");即可解決ajax跨域的問題,其中星號代表允許全部請求

$.ajax({       
           type: "post",
           url: "http://192.168.1.88/testAjaxJson",
           contentType: "application/json",
           dataType:  "json",
           success: function(){
         alert("request succeed");
       }
});
@Controller 
public class TestController {         
    /** 
     * 使用普通json方式跨域請求 
     * @param response 
     */ 
    @RequestMapping(value="/testAjaxJson")  
    public void testAjaxJson(HttpServletResponse response){  
        try {  
            // 這里設置為任意域請求都能獲取到數據
            response.setHeader("Access-Control-Allow-Origin","*"); 
            // 這里還可以設置接收方式,固定域 二者選其一
            response.setHeader("Access-Control-Allow-Headers", "accept, content-type");
            response.setHeader("Access-Control-Allow-Method", "POST");
            response.setHeader("Access-Control-Allow-Origin", "http://192.168.1.88");
           
response.getWriter().print(
"{\"id\":1}"); response.flushBuffer(); } catch (Exception e) { e.printStackTrace(); } } }

  在正式post之前,瀏覽器會先發出一個options請求(也叫preflight),同時header帶上origin還有Access-Control-Request-*:**之類的頭,服務器響應會返回相應的access-control-allow-origin,如果匹配,那么瀏覽器就會發送正式post,否則就會出現上述錯誤。這也解答了,跨域訪問時,我們明明發送的post請求,失敗的話,查看chrome network會發現是options方法的原因。

這里的content-type不屬於(application/x-www-form-urlencoded,multipart/form-data,text/plain)中的任何一種,所以是復雜請求。

       復雜請求   第一次是options請求,http options請求跟get、post、head等一樣,都屬於http的請求方法,options方法,用來獲取服務器端某url支持的方法,response header中allow標志支持的方法 

      第二次才是真正的請求

方法二,使用jsonp的方式請求數據,后端需返回js方法調用,返回的數據放在參數中

function testJsonp(){
    $.ajax({
        url:"http://192.168.1.88/testAjaxJsonp",
        type:"GET",//必須是get請求
        dataType:"jsonp",//請求的數據類型
        jsonp:"callback",//請求類型是回調
        jsonpCallback:"callbackFunction",//數據請求成功時回調的方法
        data:{  
        },//請求的數據
        success:function(data){//執行完成返回的數據
            alert(data.id);//輸出值是1
        }
    });
}
@Controller 
public class TestController {  
    @RequestMapping(value="/testAjaxJsonp")  
    public void testAjaxJsonp(@RequestParam String callback,HttpServletResponse response){  
        try {  
       // 這里jsonp返回的數據是固定格式 文后有詳細解釋 response.getWriter().print(callback
+"({\"id\":1})"); response.flushBuffer(); } catch (Exception e) { e.printStackTrace(); } } }

jsonp跨域的原理解析

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

  JSONP是一個非官方的協議,它允許在服務器端集成Script tags返回至客戶端,通過javascript callback的形式實現跨域訪問JSONP即JSON with Padding。由於同源策略的限制,XmlHttpRequest只允許請求當前源(域名、協議、端口)的資源。如果要進行跨域請求,我們可以通過使用html的script標記來進行跨域請求,並在響應中返回要執行的script代碼,其中可以直接使用JSON傳遞javascript對象。這種跨域的通訊方式稱為JSONP。

  jsonCallback 函數jsonp123(....): 是瀏覽器客戶端注冊的,獲取跨域服務器上的json數據后,回調的函數

Jsonp原理:

  首先在客戶端注冊一個callback (如:'jsoncallback'), 然后把callback的名字(如:jsonp123)傳給服務器。注意:服務端得到callback的數值后,要用jsonp123(......)把將要輸出的json內容包括起來,此時,服務器生成 json 數據才能被客戶端正確接收。

  然后以 javascript 語法的方式,生成一個function , function 名字就是傳遞上來的參數 'jsoncallback'的值 jsonp123

  最后將 json 數據直接以入參的方式,放置到 function 中,這樣就生成了一段 js 語法的文檔,返回給客戶端。

  客戶端瀏覽器,解析script標簽,並執行返回的 javascript 文檔,此時javascript文檔數據,作為參數,
  傳入到了客戶端預先定義好的 callback 函數(如上例中jquery $.ajax()方法封裝的的success: function (json))里.(動態執行回調函數)

  可以說jsonp的方式原理上和<script src="http://跨域/...xx.js"></script>是一致的(qq空間就是大量采用這種方式來實現跨域數據交換的) .JSONP是一種腳本注入(Script Injection)行為,所以也有一定的安全隱患.

  注意,jquey是不支持post方式跨域的.

 

希望總結可以幫助到大家


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM