跨站HTTP請求(Cross-site HTTP request)是指發起請求的資源所在域不一樣於請求指向的資源所在域的HTTP請求。javascript
好比說,我在Web網站A(www.a.com)中經過<img>標籤引入了B站的資源(www.b.com/images/1.jpg),那麼A站會向B站發起一個跨站請求。html
這種圖片資源的跨站請求是被容許的,相似的跨站請求還有CSS文件,JavaScript文件等。java
可是若是是在腳本中發起HTTP請求,出於安全考慮,會被瀏覽器限制。好比,使用 XMLHttpRequest 對象發起 HTTP 請求就必須遵照 同源策略。windows
所謂「同源策略」是指Web應用程序只能使用 XMLHttpRequest 對象向發起源所在域內發起HTTP請求,這個請求源和請求對象必須在一個域內。api
舉例來講,http://www.a.com,這個網址的協議是http,域名是www.a.com,端口默認是80。那麼如下是它的同源狀況:跨域
爲了開發出更強大,更豐富的Web應用,跨域請求是很常見的,那麼如何在不捨棄安全的狀況下進行跨域請求呢?瀏覽器
W3C推薦了一種新的機制,即跨源資源共享(Cross-Origin Resource Sharing (CORS))。安全
跨源資源共享(CORS)是經過客戶端+服務端協做聲明的方式來確保請求安全的。服務端會在HTTP請求頭中增長一系列HTTP請求參數(例如Access-Control-Allow-Origin等),來限制哪些域的請求和哪些請求類型能夠接受,而客戶端在發起請求時必須聲明本身的源(Orgin),不然服務器將不予處理,若是客戶端不做聲明,請求甚至會被瀏覽器直接攔截都到不了服務端。服務端收到HTTP請求後會進行域的比較,只有同域的請求才會處理。服務器
一個使用CORS實現跨域請求的示例:app
客戶端:
function getHello() { var xhr = new XMLHttpRequest(); xhr.open("post", "http://b.example.com/Test.ashx", true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); // 聲明請求源 xhr.setRequestHeader("Origin", "http://a.example.com"); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { var responseText = xhr.responseText; console.info(responseText); } } xhr.send(); }
服務端:
public class Test : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; // 聲明接受全部域的請求 context.Response.AddHeader("Access-Control-Allow-Origin", "*"); context.Response.Write("Hello World"); } public bool IsReusable { get { return false; } } }
CORS是服務端和客戶端協做聲明來確保請求安全的,所以,若是須要在Web API中啓用CORS也須要進行相應配置。好在微軟的ASP.NET團隊提供了官方的支持跨域的解決方案,只須要在NuGet中添加便可。
而後在App_Start/WebApiConfig.cs進行以下配置便可實現跨域訪問:
public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API 配置和服務 // 將 Web API 配置爲僅使用不記名令牌身份驗證。 config.SuppressDefaultHostAuthentication(); config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); // Web API 路由 config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); // 容許Web API跨域訪問 EnableCrossSiteRequests(config); config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); } private static void EnableCrossSiteRequests(HttpConfiguration config) { var cors = new EnableCorsAttribute( origins: "*", headers: "*", methods: "*" ); config.EnableCors(cors); } }
因爲IE10如下瀏覽器不支持CORS,因此目前在國內CORS並非主流的跨域解決方案,可是隨着windows 10的發佈,IE的逐漸衰落,能夠預見,在不遠的未來CORS將成爲跨域的標準解決方案之一。
參考資料:
http://www.ruanyifeng.com/blog/2016/04/cors.html
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
JavaScript中的跨域解決方案彙總: