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上傳不需要代理。