1、跨域問題僅僅發生在Javascript發起AJAX調用,或者Silverlight發起服務調用時,其根本原因是因為瀏覽器對於這兩種請求,所給予的權限是較低的,通常只允許調用本域中的資源,除非目標服務器明確地告知它允許跨域調用。假設我們頁面或者應用已在 http://www.test1.com 上了,而我們打算從 http://www.test2.com 請求提取數據。一般情況下,如果我們直接使用 AJAX 來請求將會失敗,瀏覽器也會返回“源不匹配”的錯誤,"跨域"也就以此由來。
2、什么是跨域呢?
json格式:
{
"message":"獲取成功",
"state":"1",
"result":{"name":"工作組1","id":1,"description":"11"}
}
jsonp格式:
callback({
"message":"獲取成功",
"state":"1",
"result":{"name":"工作組1","id":1,"description":"11"}
})
看出來區別了吧,在url中callback傳到后台的參數是神馬callback就是神馬,jsonp比json外面有多了一層,callback()。
只需要給全局注冊一個JsonCallbackAttribute,就可以判斷接口的訪問是屬於跨域,還是非跨域,正常的返回。
因為我們的接口,可能是用來給 移動端(Android 、IOS)做數據接口,也有可能是給網站用,所以,考慮到可能存在跨域的問題。
GlobalConfiguration.Configuration.Filters.Add(new JsonCallbackAttribute());
public class JsonCallbackAttribute : ActionFilterAttribute
{
private const string CallbackQueryParameter = "callback";
public override void OnActionExecuted(HttpActionExecutedContext context)
{
var callback = string.Empty;
if (IsJsonp(out callback))
{
var jsonBuilder = new StringBuilder(callback);
jsonBuilder.AppendFormat("({0})", context.Response.Content.ReadAsStringAsync().Result);
context.Response.Content = new StringContent(jsonBuilder.ToString());
//context.Response.Content = new StringContent("C(\"a\")");
}
base.OnActionExecuted(context);
}
private bool IsJsonp(out string callback)
{
callback = System.Web.HttpContext.Current.Request.QueryString[CallbackQueryParameter];
return !string.IsNullOrEmpty(callback);
}
結合下面圖片不難開出,請求的地址帶回了,callback的參數標識。
當然也可以用解決跨域問題的jQuery插件-jquery-jsonp,有第一種方式的基礎,使用jsonp插件也就比較簡單了,server端代碼無需任何改動。
5、服務端直接修改配置文件,個人認為這種方式好一點,畢竟我們所寫的api是對外公開的,安全訪問的控制還是要通過其他方法來保證。
針對ASP.NET MVC,只需要在web.config中添加如下的內容即可
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
針對ASP.NET Web API,除了上面這樣的設置,還需要添加一個特殊的設計,就是為每個APIController添加一個OPTIONS的方法,但無需返回任何東西。
public string Options()
{
return null; // HTTP 200 response with empty body
}
6、還有用CORS(跨域資源共享,Cross-Origin Resource Sharing)來解決的, CORS定義一種跨域訪問的機制,可以讓AJAX實現跨域訪問。CORS 允許一個域上的網絡應用向另一個域提交跨域 AJAX 請求。實現此功能非常簡單,只需由服務器發送一個響應標頭即可。
也可以設置指定的域名,如域名 http://www.test2.com ,那么就允許來自這個域名的請求:

