跨域解決方案一:使用CORS實現跨域


跨站HTTP請求(Cross-site HTTP request)是指發起請求的資源所在域不同於請求指向的資源所在域的HTTP請求。

比如說,我在Web網站A(www.a.com)中通過<img>標簽引入了B站的資源(www.b.com/images/1.jpg),那么A站會向B站發起一個跨站請求。

這種圖片資源的跨站請求是被允許的,類似的跨站請求還有CSS文件,JavaScript文件等。

 

但是如果是在腳本中發起HTTP請求,出於安全考慮,會被瀏覽器限制。比如,使用 XMLHttpRequest 對象發起 HTTP 請求就必須遵守 同源策略

所謂“同源策略”是指Web應用程序只能使用 XMLHttpRequest 對象向發起源所在域內發起HTTP請求,這個請求源和請求對象必須在一個域內。

舉例來說,http://www.a.com,這個網址的協議是http,域名是www.a.com,端口默認是80。那么以下是它的同源情況:

  • http://www.a.com/index.html 同源
  • https://www.a.com/a.html 不同源(協議不同)
  • http://service.a.com/testService/test 不同源(域名不同)
  • http://www.b.com/index.html 不同源(域名不同)
  • http://www.a.com:8080/index.html 不同源(端口不同)

為了開發出更強大,更豐富的Web應用,跨域請求是很常見的,那么如何在不舍棄安全的情況下進行跨域請求呢?

W3C推薦了一種新的機制,即跨源資源共享(Cross-Origin Resource Sharing (CORS))。

跨源資源共享(CORS)是通過客戶端+服務端協作聲明的方式來確保請求安全的。服務端會在HTTP請求頭中增加一系列HTTP請求參數(例如Access-Control-Allow-Origin等),來限制哪些域的請求和哪些請求類型可以接受,而客戶端在發起請求時必須聲明自己的源(Orgin),否則服務器將不予處理,如果客戶端不作聲明,請求甚至會被瀏覽器直接攔截都到不了服務端。服務端收到HTTP請求后會進行域的比較,只有同域的請求才會處理。

一個使用CORS實現跨域請求的示例:

客戶端:

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;
           }
       }
   }

在Web API中啟用跨域訪問

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將成為跨域的標准解決方案之一。

demo下載(bd36)

參考資料:

https://www.w3.org/TR/cors/

http://www.ruanyifeng.com/blog/2016/04/cors.html

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM