CROS是現在主流解決跨域問題的方案,未來估計也是趨勢。
Cross-Origin Resource Sharing (CORS) 是W3c工作草案,它定義了在跨域訪問資源時閱讀器和服務器之間如何通訊。CORS背后的基本思想是使用自定義的HTTP頭部允許閱讀器和服務器相互了解對方,從而決定要求或響應成功與否。
CORS與JSONP相比,更加先進、方便和可靠。
JSONP只能實現GET要求,而CORS支持所有類型的HTTP要求。
使用CORS,開發者可使用普通的XMLHttpRequest發起要求和取得數據,比起JSONP有更好的毛病處理。
JSONP主要被老的閱讀器支持,它們常常不支持CORS,而絕大多數現代閱讀器都已支持了CORS。
對1個簡單的要求,沒有自定義頭部,要末使用GET,要末使用POST,它的主體是text/plain,要求用1個名叫Orgin的額外的頭部發送。Origin頭部包括要求頁面的頭部(協議,域名,端口),這樣服務器可以很容易的決定它是不是應當提供響應。
服務器端對CORS的支持,主要就是通過設置Access-Control-Allow-Origin來進行的。
一樣的還是http://blog.csdn.net/saytime/article/details/51540876的案例,用jsonp(8080)頁面的按鈕去獲得other(8888)中jsp的數據。(摹擬servlet接口)
http://localhost:8080/jsonp/index.jsp
<%@ page language="java" contentType="text/html; charset=UTF⑻" pageEncoding="UTF⑻"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
function jsonp_fun(){
$.ajax({
url:'http://localhost:8888/other/index.jsp',
type:'post',
dataType:'text',
success:function(data){
console.log(data);
}
});
}
</script>
</head>
<body>
<input type="button" value="jsonp" onclick="jsonp_fun()"/>
</body>
</html>
http://localhost:8888/other/index.jsp
<%@ page language="java" contentType="text/html; charset=UTF⑻" pageEncoding="UTF⑻"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
</head>
<body>
other domain
</body>
</html>
點擊按鈕,發送要求。控制臺輸出以下:
查看http要求信息,發現狀態碼是200,但是就是提示跨域。
其實寫的很明白了,XMLHttpRequest不能加載8888端口的數據,在要求的資源上沒有Access-Control-Allow-Origin的頭部header,因此8080這個域沒有訪問權限。
加入響應頭。
response.setHeader("Access-Control-Allow-Origin","*");
<%@ page language="java" contentType="text/html; charset=UTF⑻"
pageEncoding="UTF⑻"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
<script type="text/javascript" src="js/jquery.min.js"></script>
</head>
<body>
<%
response.setHeader("Access-Control-Allow-Origin","*");
%>
other domain
</body>
</html>
然后再發送ajax要求。
查看http要求信息,對照之前的http要求信息。
response.setHeader("Access-Control-Allow-Origin","*");
這里*為通配符,表示允許所有的域要求來源。1般情況下,為了安全,設置為自己信任的域名,表示僅供信任的域名訪問,其他域名也就訪問不了了。
response.setHeader("Access-Control-Allow-Origin","http://localhost:8080");
這樣設置一樣可以訪問,這里就不貼圖了,這里的域信息必須完全匹配,包括端口,為了演示,下面設置為
response.setHeader("Access-Control-Allow-Origin","http://localhost");
自己看信息呀,照舊跨域,所以設置的時候要注意。
Access-Control-Allow-Methods:表示允許要求的要求類型,比如GET,POST,OPTIONS,PUT等。
<%
response.setHeader("Access-Control-Allow-Origin","*");
response.setHeader("Access-Control-Allow-Methods","GET,POST");
%>
設置成以下,一樣可以訪問,由于我們ajax方法設置的是post,如果我們改成put,然后要求結果以下:
Access-Control-Request-Method – 該項內容是實際要求的種類,可以是GET、POST之類的簡單要求,也能夠是PUT、DELETE等等。
Access-Control-Request-Headers – 該項是1個以逗號分隔的列表,當中是復雜要求所使用的頭部。
這里有幾個問題,我也不是很清楚。
1、首先是這里的Request Method:OPTIONS,這個OPTIOINS很奇怪,明明是發送的put要求,個人估計在這類場景下,客戶端發起的這個 OPTIONS 可以說是1個“預要求”,用于探測后續真正需要發起的跨域 POST 要求對服務器來講是不是是安全可接受的,由于跨域提交數據對服務器來講可能存在很大的安全問題。這里提1下,很多異步ajax上傳文件的插件在上傳前都會先發送1個OPTIONS要求,比如jquery fileupload 插件。
2、我設置成GET,發現POST要求照樣能通過,設置成POST,GET也能通過,暫時不清楚,希望知道的能給我解答。
標準的CORS要求不對cookies做任何事情,既不發送也不改變。如果希望改變這1情況,就需要將withCredentials設置為true。
另外,服務端在處理這1要求時,也需要將Access-Control-Allow-Credentials設置為true。
withCredentials屬性使得要求包括了遠程域的所有cookies,但值得注意的是,這些cookies仍舊遵照“同域”的準則,因此從代碼上你其實不能從document.cookies或回應HTTP頭當中進行讀取。
簡而言之,withCredentials:true 那末 Access-Control-Allow-Credentials:true,反之不成立。
$.ajax({
url:'http://localhost:8888/other/index.jsp',
type:'get',
dataType:'text',
success:function(data){
console.log(data);
},
xhrFields: { withCredentials: true }
});
<%
response.setHeader("Access-Control-Allow-Origin","http://localhost:8080");
response.setHeader("Access-Control-Allow-Methods","GET,POST,PUT,OPTIONS");
response.setHeader("Access-Control-Allow-Credentials","true");
%>
CROS差不多講完了,1般解決實際問題的時候,都是設置上面3個屬性。固然還有Access-Control-Request-Headers等等可以設置,這就需要你10分了解HTTP協議啦。
以后可能另外再開1個跨域異步文件上傳和Tomcat跨域問題的解決方案,觸及到crossdomain.xml,有興趣的可以先去了解了解。
下一篇 發布starrydb的演示版本