日本好好热aⅴ|国产99视频精品免费观看|日本成人aV在线|久热香蕉国产在线

  • <cite id="ikgdy"><table id="ikgdy"></table></cite>
    1. 西西軟件園多重安全檢測(cè)下載網(wǎng)站、值得信賴的軟件下載站!
      軟件
      軟件
      文章
      搜索

      首頁編程開發(fā)ASP.NET → 在ASP.NET Web API中是如何實(shí)現(xiàn)跨域資源共享?

      在ASP.NET Web API中是如何實(shí)現(xiàn)跨域資源共享?

      相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來源:Artech時(shí)間:2013/12/16 8:36:04字體大。A-A+

      作者:Artech點(diǎn)擊:21次評(píng)論:1次標(biāo)簽: 跨域

      • 類型:磁盤工具大小:18.8M語言:中文 評(píng)分:5.2
      • 標(biāo)簽:
      立即下載

      在《通過擴(kuò)展讓ASP.NET Web API支持W3C的CORS規(guī)范》中,我們通過自定義的HttpMessageHandler自行為ASP.NET Web API實(shí)現(xiàn)了針對(duì)CORS的支持,實(shí)際上ASP.NET Web API自身也是這么做的,該自定義HttpMessageHandler就是System.Web.Http.Cors.CorsMessageHandler。


         1: public class CorsMessageHandler : DelegatingHandler
         2: {
         3:     public CorsMessageHandler(HttpConfiguration httpConfiguration);
         4:     protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
         5:
         6:     public virtual Task<HttpResponseMessage> HandleCorsPreflightRequestAsync(HttpRequestMessage request, CorsRequestContext corsRequestContext, CancellationToken cancellationToken);
         7:     public virtual Task<HttpResponseMessage> HandleCorsRequestAsync(HttpRequestMessage request, CorsRequestContext corsRequestContext, CancellationToken cancellationToken);
         8: }


      CorsMessageHandler的核心功能在于:提取預(yù)定義的CORS授權(quán)策略并對(duì)當(dāng)前請(qǐng)求實(shí)施授權(quán)檢驗(yàn),并根據(jù)授權(quán)檢驗(yàn)的結(jié)果為現(xiàn)有的響應(yīng)(針對(duì)簡(jiǎn)單跨域資源請(qǐng)求和繼預(yù)檢請(qǐng)求之后發(fā)送的真正跨域資源請(qǐng)求)或者新創(chuàng)建的響應(yīng)(針對(duì)預(yù)檢請(qǐng)求)添加相應(yīng)的CORS報(bào)頭。如上面的代碼片斷所示,CorsMessageHandler定義了HandleCorsPreflightRequestAsync和HandleCorsRequestAsync虛方法,它們分別實(shí)現(xiàn)針對(duì)預(yù)檢請(qǐng)求和非預(yù)檢請(qǐng)求的CORS授權(quán)檢驗(yàn)。

      在實(shí)現(xiàn)的SendAsync方法中,當(dāng)CorsRequestContext根據(jù)表示當(dāng)前請(qǐng)求的HttpRequestMessage對(duì)象創(chuàng)建之后,會(huì)根據(jù)其IsPreflight屬性選擇調(diào)用方法HandleCorsPreflightRequestAsync或者HandleCorsRequestAsync。

      CORS授權(quán)檢驗(yàn)

      實(shí)現(xiàn)在CorsMessageHandler中的具體CORS授權(quán)檢驗(yàn)流程基本上體現(xiàn)在右圖中。它首先根據(jù)表示當(dāng)前請(qǐng)求的HttpRequestMessage對(duì)象創(chuàng)建CorsRequestContext對(duì)象。然后利用注冊(cè)的CorsProviderFactory得到對(duì)應(yīng)的CorsProvider對(duì)象,并利用后者得到針對(duì)當(dāng)前請(qǐng)求的資源授權(quán)策略,這是一個(gè)CorsPolicy對(duì)象。

      接下來,CorsMessageHandler會(huì)獲取注冊(cè)的CorsEngine。此前得到的CorsRequestContext和CorsPolicy對(duì)象會(huì)作為參數(shù)調(diào)用CorsEngine的EvaluatePolicy方法,CORS資源授權(quán)檢驗(yàn)由此開始。授權(quán)檢驗(yàn)結(jié)束之后,CorsMessageHandler會(huì)得到表示檢驗(yàn)結(jié)果的CorsResult對(duì)象。

      對(duì)于預(yù)檢請(qǐng)求,CorsMessageHandler會(huì)直接創(chuàng)建HttpResponseMessage對(duì)象予以響應(yīng)。具體來說,如果預(yù)檢請(qǐng)求通過了授權(quán)檢驗(yàn),一個(gè)狀態(tài)為“200, OK”的HttpResponseMessage會(huì)被創(chuàng)建出來,通過CorsResult得到CORS響應(yīng)報(bào)頭會(huì)被添加到這個(gè)HttpResponseMessage對(duì)象的報(bào)頭集合中。如果授權(quán)檢驗(yàn)失敗,創(chuàng)建的HttpResponseMessage具有的狀態(tài)為“400, Bad Request”,CorsResult攜帶的錯(cuò)誤響應(yīng)會(huì)作為響應(yīng)的主體內(nèi)容。

      對(duì)于非預(yù)檢請(qǐng)求,它會(huì)將當(dāng)前請(qǐng)求傳遞給消息處理管道的后續(xù)部分進(jìn)行進(jìn)一步處理,并最終得到表示響應(yīng)消息的HttpResponseMessage。只有在請(qǐng)求通過授權(quán)檢查的情況下,由CorsResult得到的CORS響應(yīng)報(bào)頭才會(huì)被添加到此HttpResponseMessage的報(bào)頭集合中。

      實(shí)例演示:創(chuàng)建MyCorsMessageHandler模擬具體采用的授權(quán)檢驗(yàn)

      為了讓讀者朋友們對(duì)實(shí)現(xiàn)在CorsMessageHandler中的具體CORS資源授權(quán)流程具有更加深刻的認(rèn)識(shí),我們現(xiàn)在將這樣的授權(quán)檢驗(yàn)邏輯實(shí)現(xiàn)在一個(gè)自定義的HttpMessageHandler中。為此我們定義了如下一個(gè)MyCorsMessageHandler類型,由于它僅僅用于模擬CorsMessageHandler大體實(shí)現(xiàn)邏輯,所以我們會(huì)忽略很多細(xì)節(jié)上(比如異常處理)的代碼。


         1: public class MyCorsMessageHandler: DelegatingHandler
         2: {
         3:     protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         4:     {
         5:         //根據(jù)當(dāng)前請(qǐng)求創(chuàng)建CorsRequestContext
         6:         CorsRequestContext context = request.CreateCorsRequestContext();
         7:
         8:         //針對(duì)非預(yù)檢請(qǐng)求:將請(qǐng)求傳遞給消息處理管道后續(xù)部分繼續(xù)處理,并得到響應(yīng)
         9:         HttpResponseMessage response = null;
        10:         if (!context.IsPreflight)
        11:         {
        12:             response = await base.SendAsync(request, cancellationToken);
        13:         }
        14:
        15:         //利用注冊(cè)的CorsPolicyProviderFactory得到對(duì)應(yīng)的CorsPolicyProvider
        16:         //借助于CorsPolicyProvider得到表示CORS資源授權(quán)策略的CorsPolicy
        17:         HttpConfiguration configuration = request.GetConfiguration();
        18:         CorsPolicy policy = await configuration.GetCorsPolicyProviderFactory().GetCorsPolicyProvider(request).GetCorsPolicyAsync(request,cancellationToken);
        19:
        20:         //獲取注冊(cè)的CorsEngine
        21:         //利用CorsEngine對(duì)請(qǐng)求實(shí)施CORS資源授權(quán)檢驗(yàn),并得到表示檢驗(yàn)結(jié)果的CorsResult對(duì)象
        22:         ICorsEngine engine = configuration.GetCorsEngine();
        23:         CorsResult result = engine.EvaluatePolicy(context, policy);
        24:
        25:         //針對(duì)預(yù)檢請(qǐng)求
        26:         //如果請(qǐng)求通過授權(quán)檢驗(yàn),返回一個(gè)狀態(tài)為“200, OK”的響應(yīng)并添加CORS報(bào)頭
        27:         //如果授權(quán)檢驗(yàn)失敗,返回一個(gè)狀態(tài)為“400, Bad Request”的響應(yīng)并指定授權(quán)失敗原因
        28:         if (context.IsPreflight)
        29:         {
        30:             if (result.IsValid)
        31:             {
        32:                 response = new HttpResponseMessage(HttpStatusCode.OK);
        33:                 response.AddCorsHeaders(result);
        34:             }
        35:             else
        36:             {
        37:                 response = request.CreateErrorResponse(HttpStatusCode.BadRequest,string.Join(" |", result.ErrorMessages.ToArray()));
        38:             }
        39:         }
        40:         //針對(duì)非預(yù)檢請(qǐng)求
        41:         //CORS報(bào)頭只有在通過授權(quán)檢驗(yàn)情況下才會(huì)被添加到響應(yīng)報(bào)頭集合中
        42:         else if (result.IsValid)
        43:         {
        44:             response.AddCorsHeaders(result);
        45:         }
        46:         return response;
        47:     }
        48: }


      如上面的代碼片斷所示,我們首選在實(shí)現(xiàn)的SendAsync方法中調(diào)用自定義的擴(kuò)展方法CreateCorsRequestContext根據(jù)表示當(dāng)前請(qǐng)求的HttpRequestMessge對(duì)象創(chuàng)建出表示針對(duì)CORS的跨域資源請(qǐng)求上下文的CorsRequestContext對(duì)象。

      然后我們根據(jù)CorsRequestContext的IsPreflight屬性判斷當(dāng)前是否是一個(gè)預(yù)檢請(qǐng)求。對(duì)于預(yù)檢請(qǐng)求,我們會(huì)直接調(diào)用基類的同名方法將請(qǐng)求傳遞給消息處理管道的后續(xù)環(huán)節(jié)作進(jìn)一步處理,并最終得到表示響應(yīng)的HttpResponse對(duì)象。

      我們接下來從表示當(dāng)前請(qǐng)求的HttpRequestMessge對(duì)象中直接獲取當(dāng)前HttpConfiguration對(duì)象,并調(diào)用擴(kuò)展方法GetCorsPolicyProviderFactory得到注冊(cè)在它上面的CorsPolicyProviderFactory,進(jìn)而得到由它提供的GetCorsPolicyProvider。通過調(diào)用此GetCorsPolicyProvider的方法GetCorsPolicyAsync,我們會(huì)得到目標(biāo)Action方法采用的CORS資源授權(quán)策略,這是一個(gè)CorsPolicy對(duì)象。

      在這之后,我們調(diào)用HttpConfiguration對(duì)象的另一個(gè)擴(kuò)展方法GetCorsEngine得到注冊(cè)其上的CorsEngine,并將此前得到的CorsRequestContext和CorsPolicy對(duì)象作為參數(shù)調(diào)用它的方法EvaluatePolicy由此開始針對(duì)當(dāng)前請(qǐng)求的CORS資源授權(quán)檢驗(yàn),并最終得到表示檢驗(yàn)結(jié)果的CorsResult。

      通過CorsResult的IsValid屬性表示當(dāng)前請(qǐng)求是否通過CORS資源授權(quán)檢驗(yàn)。對(duì)于預(yù)檢請(qǐng)求,在請(qǐng)求通過授權(quán)檢驗(yàn)的情況下,我們會(huì)創(chuàng)建一個(gè)狀態(tài)為“200, OK”的HttpResponseMessage作為最終的響應(yīng),在返回之前我們調(diào)用自定義的擴(kuò)展方法AddCorsHeaders將從CorsResult得到的CORS響應(yīng)報(bào)頭添加到此HttpResponseMessage的報(bào)頭集合中。如果請(qǐng)求沒有通過授權(quán)檢驗(yàn),我們會(huì)返回一個(gè)狀態(tài)為“400, Bad Request”的響應(yīng),通過CorsResult的ErrorMessage屬性提取的錯(cuò)誤消息(表示授權(quán)失敗的原因)會(huì)作為響應(yīng)的主體內(nèi)容。

      對(duì)于非預(yù)檢請(qǐng)求來說,只有在它通過了資源授權(quán)檢驗(yàn)的情況下,我們才會(huì)調(diào)用擴(kuò)展方法AddCorsHeaders將從CorsResult得到的CORS報(bào)頭添加響應(yīng)的報(bào)頭集合中。換句話說,對(duì)于未取得授權(quán)的非預(yù)檢跨域資源請(qǐng)求,MyCorsMessageHandler沒有對(duì)響應(yīng)作任何的改變。

      如下所示的是分別針對(duì)HttpRequestMessage和HttpResponseMessage定義的兩個(gè)擴(kuò)展方法,其中CreateCorsRequestContext方法根據(jù)HttpRequestMessage創(chuàng)建CorsRequestContext對(duì)象,而AddCorsHeaders方法則將從CorsResult中獲取的CORS響應(yīng)報(bào)頭添加到指定的HttpResponseMessage中。


         1: public static class CorsExtensions
         2: {
         3:     public static CorsRequestContext CreateCorsRequestContext(this HttpRequestMessage request)
         4:     {
         5:         CorsRequestContext context = new CorsRequestContext
         6:         {
         7:             RequestUri = request.RequestUri,
         8:             HttpMethod = request.Method.Method,
         9:             Host = request.Headers.Host,
        10:             Origin = request.GetHeader("Origin"),
        11:             AccessControlRequestMethod = request.GetHeader("Access-Control-Request-Method")
        12:         };
        13:
        14:         string requestHeaders = request.GetHeader("Access-Control-Request-Headers");
        15:         if (!string.IsNullOrEmpty(requestHeaders))
        16:         {
        17:             Array.ForEach(requestHeaders.Split(','), header => context.AccessControlRequestHeaders.Add(header.Trim()));
        18:         }
        19:         return context;
        20:     }
        21:
        22:     public static void AddCorsHeaders(this HttpResponseMessage response, CorsResult result)
        23:     {
        24:         foreach (var item in result.ToResponseHeaders())
        25:         {
        26:             response.Headers.TryAddWithoutValidation(item.Key, item.Value);
        27:         }
        28:     }
        29:
        30:     private static string GetHeader(this HttpRequestMessage request, string name)
        31:     {
        32:         IEnumerable<string> headerValues;
        33:         if (request.Headers.TryGetValues(name, out headerValues))
        34:         {
        35:             return headerValues.FirstOrDefault();
        36:         }
        37:         return null;
        38:     }
        39: }


      為了驗(yàn)證我們這個(gè)用于模擬CorsMessageHandler的自定義HttpMessageHandler是否能夠真正為ASP.NET Web API提供針對(duì)CORS的支持,我們直接將其應(yīng)用到《同源策略與JSONP》創(chuàng)建的演示實(shí)例中。我們通過上面介紹的方式為WebApi應(yīng)用安裝“Microsoft ASP.NET Web API 2 Cross-Origin Support”這個(gè)NuGet包后,將EnableCorsAttribute特性應(yīng)用到定義在ContactsController上并作如下的設(shè)置。


         1: [EnableCors("http://localhost:9527","*","*")]
         2: public class ContactsController : ApiController
         3: {
         4:     public IHttpActionResult GetAllContacts()
         5:     {
         6:         //省略實(shí)現(xiàn)
         7:     }
         8: }


      在Global.asax中,我們并不調(diào)用當(dāng)前HttpConfiguration的EnableCors方法開啟ASP.NET Web API針對(duì)CORS的支持,而是采用如下的方式將創(chuàng)建的CorsMessageHandler對(duì)象添加到消息處理管道中。如果現(xiàn)在運(yùn)行ASP.NET MVC程序,通過調(diào)用Web API以跨域Ajax請(qǐng)求得到的聯(lián)系人列表依然會(huì)顯示在瀏覽器上。


         1: public class WebApiApplication : System.Web.HttpApplication
         2: {
         3:     protected void Application_Start()
         4:     {
         5:         GlobalConfiguration.Configuration.MessageHandlers.Add(new MyCorsMessageHandler());
         6:         //其他操作
         7:     }
         8: }


      HttpConfiguration的EnableCors方法

      通過上面的介紹我們知道針對(duì)ASP.NET Web API的CORS編程首先需要做的就是在程序啟動(dòng)之前調(diào)用當(dāng)前HttpConfiguration的擴(kuò)展方法EnableCors開啟對(duì)CORS的支持,那么該方法中具體實(shí)現(xiàn)了怎樣操作呢?由于ASP.NET Web API針對(duì)CORS的支持最終是通過CorsMesssageHandler這個(gè)自定義的HttpMessageHandler來實(shí)現(xiàn)的,所以對(duì)于HttpConfiguration的擴(kuò)展方法EnableCors來說,其核心操作就是對(duì)CorsMesssageHandler予以注冊(cè)。


         1: public static class CorsHttpConfigurationExtensions
         2: {
         3:     public static void EnableCors(this HttpConfiguration httpConfiguration);
         4:     public static void EnableCors(this HttpConfiguration httpConfiguration, ICorsPolicyProvider defaultPolicyProvider);
         5: }
         6:
         7: public class AttributeBasedPolicyProviderFactory : ICorsPolicyProviderFactory
         8: {
         9:     //其他成員
        10:     public ICorsPolicyProvider DefaultPolicyProvider { get; set; }
        11: }


      如上面的代碼片斷所示,HttpConfiguration具有兩個(gè)重載的EnableCors方法。其中一個(gè)可以指定一個(gè)默認(rèn)的CorsPolicyProvider,如果調(diào)用此方法并指定一個(gè)具體的CorsPolicyProvider對(duì)象,一個(gè)AttributeBasedPolicyProviderFactory對(duì)象會(huì)被創(chuàng)建出來并注冊(cè)到HttpConfiguration上。而指定的CorsPolicyProvider實(shí)際上會(huì)作為AttributeBasedPolicyProviderFactory對(duì)象的DefaultPolicyProvider屬性。

        相關(guān)評(píng)論

        閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

        • 8 喜歡喜歡
        • 3 頂
        • 1 難過難過
        • 5 囧
        • 3 圍觀圍觀
        • 2 無聊無聊

        熱門評(píng)論

        最新評(píng)論

        發(fā)表評(píng)論 查看所有評(píng)論(1)

        昵稱:
        表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
        字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過審核才能顯示)