跨域問題是由於瀏覽器為了防止CSRF攻擊(Cross-site request forgery跨站請求偽造),避免惡意攻擊而帶來的風險而採取的同源策略限制。當一個頁面中使用XMLHTTPRequest(XHR請求)對象發送HTTP請求時,必須保證當前頁面和請求的對象是同源的,即協議、功能變數名稱和埠號要完 ...
跨域問題是由於瀏覽器為了防止CSRF攻擊(Cross-site request forgery跨站請求偽造),避免惡意攻擊而帶來的風險而採取的同源策略限制。當一個頁面中使用XMLHTTPRequest(XHR請求)對象發送HTTP請求時,必須保證當前頁面和請求的對象是同源的,即協議、功能變數名稱和埠號要完全一致,否則瀏覽器就會阻止此跨域請求返回的數據。
例如:
http://www.a.com 與 https://www.a.com 是不同源的,它們協議不同
http://www.a.com 與 http://www.b.com 是不同源的,它們功能變數名稱不同
http://www.a.com:80 與 http://www.a.com:8080 是不同源的,它們埠號不同
http://www.a.com/test1.js 與 http://www.a.com/test2.js 是同源的
跨域請求的解決方案
雖然同源限制可以有效的防止網路上的惡意攻擊,但是在實際開發應用中,我們往往需要從本站點向第三方站點發送XHR請求,這就需要有效的解決跨域問題,可以有以下幾種:
(1)JSONP:只支持GET,不支持POST請求代理:使用代理去避開跨域請求,例如www.a.com/index.html頁面去調用www.b.com/service.jsp,可以通過寫一個介面www.a.com/service.jsp,由這個介面在後端去調用www.b.com/service.jsp並取到返回值,然後再返回給index.html。
(2)服務端修改:例如在服務端頁面添加header限制:
header('Access-Control-Allow-Origin:*'); //允許所有來源訪問
header('Access-Control-Allow-Method:POST,GET'); // 允許訪問的方式
由於JSONP是最靈活,也是最常用的方式,這裡主要講解JSONP方式解決跨域問題。
JSONP原理
瀏覽器只對XHR(XMLHttpRequest)請求有同源請求限制,而對script標簽src屬性、link標簽ref屬性和img標簽src屬性沒有這這種限制,利用這個“漏洞”就可以很好的解決跨域請求。JSONP就是利用了script標簽無同源限制的特點來實現的,當向第三方站點請求時,我們可以將此請求放在<script>標簽的src屬性里,這就如同我們請求一個普通的JS腳本,可以自由的向不同的站點請求:
<script src="http://www.b.com/request?para1=1"></script>
JSONP請求實現
(1)Javascript實現
服務端:
public void ProcessRequest(HttpContext context) {
context.Response.ContentType = "text/plain";
//指定的回調函數名稱
String callbackFuncName = context.Request.QueryString["callback"];
String reponseData = "test jsonp";
//回調腳本
String scriptContent = callbackFuncName + "('" + reponseData + "'";
context.Response.Write(scriptContent);
}
前端:
<script type="text/javascript" src="http://localhost/Service.ashx?callback=jsonpCallback" />
//回調函數
function jsonpCallback(content){
alert(content); }
</script>
運行的結果顯示test jsonp,可以看出整個過程:
script標簽設置src屬性為請求的地址,並判斷回調函數作為參數服務端構建JS腳本,傳遞返回給客戶端的數據客戶端在回調函數中解析伺服器生成的數據
(2)JQuery實現
JQuery的ajax方法對JSONP方法進行了封裝,使用JQuery提供的方法變得非常簡單
前端:
<script type="text/javascript">
$.ajax({
type: "get",
async: false,
url: "http://localhost:8546/Service.ashx",
dataType: "jsonp",
success: function (data) {
alert(data);
},
error: function () {
alert('fail');
}
});
</script>