1. 程式人生 > >Firebug: 已攔截跨源請求:同源策略禁止讀取位於XXX的遠端資源。(原因:CORS 頭缺少 'Access-Control-Allow-

Firebug: 已攔截跨源請求:同源策略禁止讀取位於XXX的遠端資源。(原因:CORS 頭缺少 'Access-Control-Allow-

第一種,就是在被請求的程式中新增HTTP頭,即CORS跨域(跨域資源共享,Cross-Origin Resource Sharing)

如: Response.Headers.Add("Access-Control-Allow-Origin", "*");
// JSON
{
  'Access-Control-Allow-Origin': '*', 
}
// HTML
<meta http-equiv="Access-Control-Allow-Origin" content="*">
// PHP
header("Access-Control-Allow-Origin: *");
header
("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");

  新增此段程式碼的目的很簡單,也就是告訴瀏覽器,這個資源是執行遠端所有域名訪問的。當然,此處的也可以替換為指定的域名,出於安全考慮,建議將替換成指定的域名。
  由於IE10以下瀏覽器不支援CORS,所以目前在國內CORS並不是主流的跨域解決方案,但是隨著windows 10的釋出,IE的逐漸衰落,可以預見,在不遠的將來CORS將成為跨域的標準解決方案。

第二種,就是在被請求的伺服器上,新增HTTP響應頭。在這裡,我們就以IIS6.0為例:

//在被請求的網站上,設定HTTP頭,新增
"Access-Control-Allow-Origin:*" //值為*或指定的域名。

第三種,就是在被請求的伺服器上在被請求的專案根目錄(root下)下放以下檔案 :
crossdomain.xml

    <?xml version="1.0"?>    
    <!DOCTYPE cross-domain-policy SYSTEM "./cross-domain-policy.dtd">    
    <cross-domain-policy> <site-control permitted-cross-domain-policies
="all" />
<allow-access-from domain="*" /> <allow-http-request-headers-from domain="*" headers="*"/> </cross-domain-policy>

cross-domain-policy.dtd

    <?xml version="1.0" encoding="ISO-8859-1"?>    
    <!-- Adobe DTD for cross-domain policy files -->    
    <!-- Copyright (c) 2008-2009, Adobe Systems Inc. -->    

    <!ELEMENT cross-domain-policy (site-control?,allow-access-from*,allow-http-request-headers-from*,allow-access-from-identity*)>    

    <!ELEMENT site-control EMPTY>    
    <!ATTLIST site-control permitted-cross-domain-policies (all|by-content-type|by-ftp-filename|master-only|none) #REQUIRED>    

    <!ELEMENT allow-access-from EMPTY>    
    <!ATTLIST allow-access-from domain CDATA #REQUIRED>    
    <!ATTLIST allow-access-from to-ports CDATA #IMPLIED>    
    <!ATTLIST allow-access-from secure (true|false) "true">    

    <!ELEMENT allow-http-request-headers-from EMPTY>    
    <!ATTLIST allow-http-request-headers-from domain CDATA #REQUIRED>    
    <!ATTLIST allow-http-request-headers-from headers CDATA #REQUIRED>    
    <!ATTLIST allow-http-request-headers-from secure (true|false) "true">    

    <!ELEMENT allow-access-from-identity (signatory)>    

    <!ELEMENT signatory (certificate)>    

    <!ELEMENT certificate EMPTY>    
    <!ATTLIST certificate fingerprint CDATA #REQUIRED>    
    <!ATTLIST certificate fingerprint-algorithm CDATA #REQUIRED>    

    <!-- End of file. -->    

第四種,使用JSONP格式
即在jQuery中ajax請求引數dataType:’JSONP’:

<script> 
    $.ajax({ 
        url:"http://map.oicqzone.com/gpsApi.php?lat=22.502412986242&lng=113.93832783228", 
        type:'GET', 
        dataType:'JSONP',  // 處理Ajax跨域問題
        success: function(data){ 
            $('body').append( "Name: " + data ); 
        } 
    }); 
</script>

或者:

    <script type="text/javascript">    
        function jsonpCallback(result){     
           alert(result[1].name);     
        }     
    </script>  
    <script type="text/javascript"src="http://localhost:8080/Jsonp/jsonp.jsp?callback=jsonpCallback"></script>  

或者jquery程式碼:

    <script type="text/javascript">     
        $.getJSON("http://localhost:8080/Jsonp/jsonp.jsp?callback=?", function(json){      
            alert(json[0].name);     
        });     
     </script>  

後臺jsonp.jsp程式碼:

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%  
         String callback = request.getParameter("callback");  
         out.print(callback+"([ { name:'John',age:'19'},{ name:'joe',age:'20'}] );");  
         out.print(callback);  
    %>  

或者servlet

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/Jsonp")
public class Jsonp extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String jsonp=request.getParameter("jsonpcallback");  
        response.setContentType("text/html;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
        out.write(jsonp + "0;null");
        out.close();
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }
}

ajax請求的引數:jsonp

型別:String
在一個 jsonp 請求中重寫回調函式的名字。這個值用來替代在 “callback=?” 這種 GET 或 POST 請求中 URL 引數裡的 “callback” 部分,比如 {jsonp:’onJsonPLoad’} 會導致將 “onJsonPLoad=?” 傳給伺服器。

ajax請求的引數:jsonpCallback

型別:String
為 jsonp 請求指定一個回撥函式名。這個值將用來取代 jQuery 自動生成的隨機函式名。這主要用來讓 jQuery 生成度獨特的函式名,這樣管理請求更容易,也能方便地提供回撥函式和錯誤處理。你也可以在想讓瀏覽器快取 GET 請求的時候,指定這個回撥函式名。

注意內容:
  1、Ajax請求需要設定請求型別為Jsonp
  dataType: “jsonp”

  2、Ajax請求需要設定回撥函式,當前函式值必須與伺服器響應包含的callback名稱相同
  jsonpCallback:”fn”

  3、Ajax請求可以設定jsonp(可選),傳遞給請求處理程式或頁面,用以獲得jsonp回撥函式名的引數名,預設為:callback
  jsonp: “callback”

  4、服務端返回Json資料必須使用jsonpCallback設定的值進行包裹
  return “fn(“+JsonUtil.objectToJson(outPut)+”)”
  
第五種,使用Html5中新引進的window.postMessage方法來跨域傳送資料

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

  1、 JSONP只能實現GET請求,而CORS支援所有型別的HTTP請求。
  
  2、 使用CORS,開發者可以使用普通的XMLHttpRequest發起請求和獲得資料,比起JSONP有更好的錯誤處理。
  
  3、 JSONP主要被老的瀏覽器支援,它們往往不支援CORS,而絕大多數現代瀏覽器都已經支援了CORS。
  
  對一個簡單的請求,沒有自定義頭部,要麼使用GET,要麼使用POST,它的主體是text/plain,請求用一個名叫Orgin的額外的頭部發送。Origin頭部包含請求頁面的頭部(協議,域名,埠),這樣伺服器可以很容易的決定它是否應該提供響應。
  伺服器端對於CORS的支援,主要就是通過設定Access-Control-Allow-Origin來進行的。
  Header set Access-Control-Allow-Origin *
  為了防止XSS攻擊我們的伺服器, 我們可以限制域,比如: Access-Control-Allow-Origin: http://blog.csdn.net
  很多服務都已經提供了CORS支援,比如 AWS 支援跨域資源分享功能CORS,向S3上傳不需要代理。