ajax處理跨域有幾種方式?實現原理是什麼?


一、什麼是跨域

我們先回顧一下域名地址的組成:

http:// www . google : 8080 / script/jquery.js

      http:// (協議號)

               www  (子域名)

             google (主域名)

               8080 (端口號)

script/jquery.js (請求的地址)

* 當協議、子域名、主域名、端口號中任意一各不相同時,都算不同的“域”。

* 不同的域之間相互請求資源,就叫“跨域”。

比如:http://www.abc.com/index.html 請求 http://www.def.com/sever.php

 二、出現跨域問題的情況

由於在工作中需要使用AJAX請求其他域名下的請求,但是會出現拒絕訪問的情況,這是因爲基於安全的考慮,AJAX只能訪問本地的資源,而不能跨域訪問。

比如說你的網站域名是aaa.com,想要通過AJAX請求bbb.com域名中的內容,瀏覽器就會認爲是不安全的,所以拒絕訪問。

會出現跨域問題的幾種情況:

 

三、處理跨域的方法1 -- 代理

這種方式是通過後臺(ASP、PHP、JAVA、ASP.NET)獲取其他域名下的內容,然後再把獲得內容返回到前端,這樣因爲在同一個域名下,所以就不會出現跨域的問題。

比如在北京(www.beijing.com/sever.php)和上海(www.shanghai.com/sever.php)各有一個服務器,北京的後端(www.beijing.com/sever.php)直接訪問上海的服務,然後把獲取的響應值返回給前端。也就是北京的服務在後臺做了一個代理,前端只需要訪問北京的服務器也就相當與訪問了上海的服務器。這種代理屬於後臺的技術,所以不展開敘述。

 

四、處理跨域的方法2 -- JSONP

假設在http://www.aaa.com/index.php這個頁面中向http://www.bbb.com/getinfo.php提交GET請求,那麼我們在www.aaa.com頁面中添加如下代碼:

1
2
3
4
5
6
7
var eleScript= document.createElement("script");//創建一個script元素
 
eleScript.type = "text/javascript";//聲明類型、
 
eleScript.src = "http://www.bbb.com/getinfo.php"; //添加src屬性 引入跨域訪問的url
 
document.getElementsByTagName("HEAD")[0].appendChild(eleScript);//在頁面中添加新創建的script元素

當GET請求從http://www.bbb.com/getinfo.php返回時,可以返回一段JavaScript代碼,這段代碼會自動執行,可以用來負責調用http://www.aaa.com/index.php頁面中的一個callback函數。看下面一個列子:

www.aaa.com頁面中:

1
2
3
4
5
6
7
8
9
10
11
<script>
 
  function jsonp( json ){
 
    document.write( json.name ); //輸出周星馳
 
}
 
<script>
 
<script src="http://www.bbb.com/getinfo.php"></script>

www.bbb.com頁面中:

  jsonp({ "name":"周星馳","age":45 });

也就是在www.aaa.com頁面中聲明,在www.bbb.com頁面中調用。但是JSONP只支持 “GET” 請求,但不支持 “POST” 請求。

 

五、處理跨域的方法3 -- XHR2(推薦方法)

“XHR2” 全稱 “XMLHttpRequest Level2” 是HTML5提供的方法,對跨域訪問提供了很好的支持,並且還有一些新的功能。

* IE10一下的版本都不支持

* 只需要在服務器端頭部加上下面兩句代碼:

  header( "Access-Control-Allow-Origin:*" );

  header( "Access-Control-Allow-Methods:POST,GET" );



ajax跨域post請求的java代理實現

    最近開發的項目有個功能的需求如下:根據用戶提供的外部鏈接(outter_url),在頁面填寫好查詢條件(param)並向該url發起查詢請求,查詢返回的數據來動態生成html的table來顯示數據,同時要求請求的方法是post請求。

在開發過程中用的是jquery的異步請求。問題出現了,網上搜了半天沒有發現實現jquery跨域進行post請求的解決方案(貌似不支持),所以自己用java代碼來發起post跨域請求

  關於實現思路的幾點說明:

1)      項目中用的是spring,所以這個請求是在spring某個controller的方法中實現的,爲了方便說明問題該方法假設爲(ajaxProxy)

2)      在jsp頁面中通過jquery的ajax方法,發起一個請求,該請求的url映射到1)中所說的那個ajaxProxy方法,並把查詢條件(param)一起傳遞到ajaxProxy方法.部分代碼如下

        

[javascript] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. $.ajax({  
  2.     type : "GET",  
  3.          //映射到controller對應方法的url  
  4.          url : "<c:url value='/user/put/queryItems'/>",  
  5.         //查詢條件數據  
  6.         data : param,  
  7.     dataType : 'json',  
  8.     success : function(data) {//動態生成table,代碼略}  


3)      在ajaxProxy方法中,用HttpURLConnection鏈接outter_url,並設置connection的請求方法爲Post,併發送查詢條件(param),該部分的代碼實現如下:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. URL connect = new URL(outer_url);  
  2.   
  3. HttpURLConnection connection =(HttpURLConnection)connect.openConnection();  
  4.   
  5. Connection.setRequestMethod(“Post”);  
  6.   
  7. //發送查詢條件  
  8.   
  9. OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());  
  10.   
  11. out.wirte(param);  
  12.   
  13. out.flush();  


4)      接收數據並返回數據,jsp頁面中ajax的success方法處理接收到的數據data,並把data返回就可以了,接收數據的代碼如下

       

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. StringBuffer data = new StringBuffer();  
  2. BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "gb2312"));  
  3. String line;              
  4. while ((line = reader.readLine()) != null) {          
  5.     data.append(line);            
  6. }  
  7.   
  8. return data;  

綜上所述,實現跨域post請求的java實現代碼如下

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. @RequestMapping("queryItems")  
  2. public @ResponseBody  
  3. String ajaxProxy(String name, String startTime, String endTime,  
  4.         String tag, Model m, HttpServletRequest req) throws UnsupportedEncodingException {  
  5.   
  6.         //拼接查詢條件,組成json格式的數據發送    
  7.         JSONObject node = new JSONObject();         
  8.  try {    
  9.           
  10.       JSONObject param = new JSONObject();      
  11.        param.put("type""");    
  12.        param.put("typevalue""");    
  13.         //param.put("key", name);    
  14.         param.put("key"new String(name.toString().getBytes("utf-8"), "gbk"));  
  15.         param.put("start_time", startTime);    
  16.         param.put("end_time", endTime);    
  17.         param.put("tags", tag);    
  18.         node.put("param", param);    
  19.                                     
  20.         JSONObject user = new JSONObject();  
  21.         user.put("userid""123");  
  22.         node.put("user", user);  
  23.           
  24.         JSONObject device = new JSONObject();  
  25.         device.put("dnum""123");  
  26.         node.put("device", device);  
  27.           
  28.         JSONObject developer = new JSONObject();  
  29.         developer.put("apikey""******");  
  30.         developer.put("secretkey""*****");     
  31.         node.put("developer", developer);  
  32.          
  33.         node.put("action", action);  
  34.           
  35.     } catch (JSONException e1) {  
  36.         // TODO Auto-generated catch block  
  37.         e1.printStackTrace();  
  38.     }        
  39.       
  40.     // 使用POST方式向目的服務器發送請求  
  41.     URL connect;  
  42.     StringBuffer data = new StringBuffer();  
  43.     try {  
  44.         connect = new URL("outter_url");  
  45.         HttpURLConnection connection = (HttpURLConnection)connect.openConnection();  
  46.         connection.setRequestMethod("POST");  
  47.         connection.setDoOutput(true);  
  48.          
  49.         OutputStreamWriter paramout = new OutputStreamWriter(  
  50.                 connection.getOutputStream(),"UTF-8");  
  51.         paramout.write(json);  
  52.         paramout.flush();  
  53.   
  54.         BufferedReader reader = new BufferedReader(new InputStreamReader(  
  55.                 connection.getInputStream(), "gb2312"));  
  56.         String line;              
  57.         while ((line = reader.readLine()) != null) {          
  58.             data.append(line);            
  59.         }  
  60.       
  61.         paramout.close();  
  62.         reader.close();  
  63.     } catch (Exception e) {  
  64.         // TODO Auto-generated catch block  
  65.         e.printStackTrace();  
  66.     }  
  67.     return data.toString();  
  68.       
  69. }  

發佈了164 篇原創文章 · 獲贊 26 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章