日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

深入剖析.NETCORE中CORS(跨站资源共享)

發(fā)布時(shí)間:2023/12/4 asp.net 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入剖析.NETCORE中CORS(跨站资源共享) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

由于現(xiàn)代互聯(lián)網(wǎng)的飛速發(fā)展,我們在開發(fā)現(xiàn)代 Web 應(yīng)用程序中,經(jīng)常需要考慮多種類型的客戶端訪問服務(wù)的情況;而這種情況放在15年前幾乎是不可想象的,在那個(gè)時(shí)代,我們更多的是考慮怎么把網(wǎng)頁快速友好的嵌套到服務(wù)代碼中,經(jīng)過服務(wù)器渲染后輸出HTML到客戶端,沒有 iOS,沒有 Android,沒有 UWP。更多的考慮是 防止 XSS,在當(dāng)時(shí)的環(huán)境下,XSS一度成為各個(gè)站長的噩夢,甚至網(wǎng)站開發(fā)的基本要求都要加上:必須懂防 XSS 攻擊。

CORS 定義

言歸正傳,CORS(Cross-Origin Resource Sharing)是由 W3C 指定的標(biāo)準(zhǔn),其目的是幫助在各個(gè)站點(diǎn)間的資源共享。CORS 不是一項(xiàng)安全標(biāo)準(zhǔn),啟用 CORS 實(shí)際上是讓站點(diǎn)放寬了安全標(biāo)準(zhǔn);通過配置 CORS,可以允許配置中的請求源執(zhí)行允許/拒絕的動(dòng)作。

在 .NETCore 中啟用 CORS

在 .NETCore 中,已經(jīng)為我們集成好 CORS 組件 Microsoft.AspNetCore.Cors,在需要的時(shí)候引入該組件即可,Microsoft.AspNetCore.Cors 的設(shè)計(jì)非常的簡潔,包括兩大部分的內(nèi)容,看圖:

從上圖中我們可以看出,左邊是入口,是我們常見的 AddCors/UseCors,右邊是 CORS 的核心配置和驗(yàn)證,配置對象是 CorsPolicyBuilder 和 CorsPolicy,驗(yàn)證入口為 CorsService,中間件 CorsMiddleware 提供了攔截驗(yàn)證入口。

CorsService 是整個(gè) CORS 的核心實(shí)現(xiàn),客戶端的請求流經(jīng)中間件或者AOP組件后,他們在內(nèi)部調(diào)用 CorsService 的相關(guān)驗(yàn)證方法,在 CorsService 內(nèi)部使用配置好的 PolicyName 拉去相關(guān)策略進(jìn)行請求驗(yàn)證,最終返回驗(yàn)證結(jié)果到客戶端。

Microsoft.AspNetCore.Mvc.Cors

通常情況下,我們會在 Startup 類中的 ConfigureServices(IServiceCollection services) 方法內(nèi)部調(diào)用 AddCors() 來啟用 CROS 策略,但是,該 AddCors() 并不是上圖中 CorsServiceCollectionExrensions 中的 AddCors 擴(kuò)展方法。

實(shí)際上,在 ConfigureServices 中調(diào)用的 AddCors 是處于程序集 Microsoft.AspNetCore.Mvc.Cors ;在 Microsoft.AspNetCore.Mvc.Cors 內(nèi)部的擴(kuò)展方法 AddCors() 中,以 AOP 方式定義了對 EnableCorsAttribute/DisableCorsAttributeAttribute 的攔截檢查。

具體做法是在程序集 Microsoft.AspNetCore.Mvc.Cors 內(nèi)部,定義了類 CorsApplicationModelProvider ,當(dāng)我們調(diào)用 AddCors 擴(kuò)展方法的時(shí)候,將進(jìn)一步調(diào)用 CorsApplicationModelProvider.OnProvidersExecuting(ApplicationModelProviderContext context) 方法,從而執(zhí)行檢查 EnableCorsAttribute/DisableCorsAttributeAttribute 策略。

所以,我們在 ConfigureServices 中調(diào)用的 AddCore,其實(shí)是在該程序集內(nèi)部定義的類:MvcCorsMvcCoreBuilderExtensions 的擴(kuò)展方法,我們看 MvcCorsMvcCoreBuilderExtensions 的定義

public static class MvcCorsMvcCoreBuilderExtensions {public static IMvcCoreBuilder AddCors(this IMvcCoreBuilder builder){...AddCorsServices(builder.Services);...}public static IMvcCoreBuilder AddCors(this IMvcCoreBuilder builder,Action<CorsOptions> setupAction){...AddCorsServices(builder.Services);...}public static IMvcCoreBuilder ConfigureCors(this IMvcCoreBuilder builder,Action<CorsOptions> setupAction){...}// Internal for testing.internal static void AddCorsServices(IServiceCollection services){services.AddCors();services.TryAddEnumerable(ServiceDescriptor.Transient<IApplicationModelProvider, CorsApplicationModelProvider>());services.TryAddTransient<CorsAuthorizationFilter, CorsAuthorizationFilter>();} }

重點(diǎn)就在上面的 AddCorsServices(IServiceCollection services) 方法中, 在方法中調(diào)用了 CORS 的擴(kuò)展方法 AddCors()。

那么我們就要問, CorsApplicationModelProvider 是在什么時(shí)候被初始化的呢?答案是在 startup 中 ConfigureServices(IServiceCollection services) 方法內(nèi)調(diào)用 services.AddControllers() 的時(shí)候。在AddControllers() 方法內(nèi)部,調(diào)用了 AddControllersCore 方法

private static IMvcCoreBuilder AddControllersCore(IServiceCollection services) {// This method excludes all of the view-related services by default.return services.AddMvcCore().AddApiExplorer().AddAuthorization().AddCors().AddDataAnnotations().AddFormatterMappings(); }

理解了 CORS 的執(zhí)行過程,下面我們就可以開始了解應(yīng)該怎么在 .NETCore 中使用 CORS 的策略了

CORS 啟用的三種方式

在 .NETCore 中,可以通過以下三種方式啟用 CORS

1、使用默認(rèn)策略/命名策略的中間件的方式 2、終結(jié)點(diǎn)路由 + 命名策略 3、命名策略 + EnableCorsAttribute

通過上面的三種方式,可以靈活在程序中控制請求源的走向,但是,殘酷的事實(shí)告訴我們,一般情況下,我們都是會對全站進(jìn)行 CORS。所以,現(xiàn)實(shí)情況就是在大部分的 Web 應(yīng)用程序中, CORS 已然成為皇帝的新裝,甚至有點(diǎn)累贅。

CorsPolicyBuilder(CORS策略)

通過上面的 CORS 思維導(dǎo)圖,我們已經(jīng)大概了解了 CORS 的整個(gè)結(jié)構(gòu)。由上圖我們知道,CorsPolicyBuilder 位于命名空間 Microsoft.AspNetCore.Cors.Infrastructure 中。在內(nèi)部提供了兩種基礎(chǔ)控制策略:全開/半開。這兩種策略都提供了基本的方法供開發(fā)者直接調(diào)用,非常的貼心。

全開

public CorsPolicyBuilder AllowAnyHeader(); public CorsPolicyBuilder AllowAnyMethod(); public CorsPolicyBuilder AllowAnyOrigin(); public CorsPolicyBuilder AllowCredentials();

半開

public CorsPolicyBuilder DisallowCredentials(); public CorsPolicyBuilder WithHeaders(params string[] headers); public CorsPolicyBuilder WithMethods(params string[] methods); public CorsPolicyBuilder WithOrigins(params string[] origins);

上面的策略定義從字面理解就可以知道其用途,實(shí)際上呢,他們的實(shí)現(xiàn)原理也是非常的簡單。在 CorsPolicyBuilder 內(nèi)部維護(hù)著一個(gè) CorsPolicy 對象,當(dāng)你使用全開/半開方式配置策略的時(shí)候,builder 會將配置寫入內(nèi)部 CorsPolicy 中存儲備用。

比如半開 WithOrigins(params string[] origins);,通過迭代器將配置的源寫入 _policy.Origins 中。

public CorsPolicyBuilder WithOrigins(params string[] origins) {foreach (var origin in origins){var normalizedOrigin = GetNormalizedOrigin(origin);_policy.Origins.Add(normalizedOrigin);}return this; }

開始使用

在理解了配置的過程后,我們就可以進(jìn)入真正的使用環(huán)節(jié)了,通過上面的學(xué)習(xí)我們知道,啟用 CORS 有三種方式,咱們一步一步來。

使用默認(rèn)策略/命名策略的中間件的方式

所謂的命名策略就是給你的策略起個(gè)名字,默認(rèn)策略就是沒有名字,所有的入口都使用同一個(gè)策略,下面的代碼演示了命名策略

private readonly string CORS_ALLOW_ORGINS = "cors_allow_orgins";public void ConfigureServices(IServiceCollection services) {services.AddCors(options =>{options.AddPolicy(CORS_ALLOW_ORGINS, policy =>{policy.WithOrigins("http://localhost:5500", "http://localhost:8099");});});services.AddControllers().AddJsonOptions(options =>{options.JsonSerializerOptions.Converters.Add(new StringJsonConverter());}); }// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseRouting();app.UseCors(CORS_ALLOW_ORGINS);app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapControllers();}); }

上面的代碼演示了如何在站點(diǎn)中全局終結(jié)點(diǎn)啟用 CORS,首先聲明了命名策略 corsalloworgins ,然后將其用 AddCors() 添加到 CORS 中,最后使用 UseCors() 啟用該命名策略,需要注意的是,AddCors() 和 UseCors() 必須成對出現(xiàn),并且要使用同一個(gè)命名策略。

終結(jié)點(diǎn)路由 + 命名策略

.NETCore 支持通過對單個(gè)路由設(shè)置 CORS 命名策略,從而可以實(shí)現(xiàn)在一個(gè)系統(tǒng)中,對不同的業(yè)務(wù)提供個(gè)性化的支持。終結(jié)點(diǎn)路由 + 命名策略的配置和上面的命名策略基本相同,僅僅是在配置路由的時(shí)候,只需要對某個(gè)路由增加 RequireCors 的配置即可

private readonly string CORS_ALLOW_ORGINS = "cors_allow_orgins"; public void ConfigureServices(IServiceCollection services) {services.AddCors(options =>{options.AddPolicy(CORS_ALLOW_ORGINS, policy =>{policy.WithOrigins("http://localhost:5500", "http://localhost:8099");});});services.AddControllers().AddJsonOptions(options =>{options.JsonSerializerOptions.Converters.Add(new StringJsonConverter());}); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseRouting();app.UseCors();app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapControllerRoute("weatherforecast", "{controller=WeatherForecast}/{action=Get}").RequireCors(CORS_ALLOW_ORGINS);// endpoints.MapControllers();}); }

上面的代碼,指定了路由 weatherforecast 需要執(zhí)行 CORS 策略 CORSALLOWORGINS。通過調(diào)用 RequireCors() 方法,傳入策略名稱,完成 CORS 的配置。RequireCors 方法是在程序集 Microsoft.AspNetCore.Cors 內(nèi)部的擴(kuò)展方法,具體是怎么啟用策略的呢,其實(shí)就是在內(nèi)部給指定的終結(jié)點(diǎn)路由增加了 EnableCorsAttribute ,這就是下面要說到的第三種啟用 CORS 的方式。

來看看 RequireCors() 內(nèi)部的代碼

public static TBuilder RequireCors<TBuilder>(this TBuilder builder, string policyName) where TBuilder : IEndpointConventionBuilder {if (builder == null){throw new ArgumentNullException(nameof(builder));}builder.Add(endpointBuilder =>{endpointBuilder.Metadata.Add(new EnableCorsAttribute(policyName));});return builder; }

命名策略 + EnableCorsAttribute

最后一種啟用 CORS 的方式是使用 EnableCorsAttribute 特性標(biāo)記,和 RequireCors 方法內(nèi)部的實(shí)現(xiàn)不同的是,這里說的 EnableCorsAttribute 是顯式的指定到控制器上,在應(yīng)用 EnableCorsAttribute 的時(shí)候,你可以應(yīng)用到根控制器或者子控制器上,如果是對根控制器進(jìn)行標(biāo)記,被標(biāo)記的根控制器和他的所有子控制器都將受指定 CORS 策略的影響;反之,如果只是對子控制器進(jìn)行標(biāo)記,CORS 策略也只對當(dāng)前控制器產(chǎn)生影響。

CORS 的初始化

public void ConfigureServices(IServiceCollection services) {services.AddCors(options =>{options.AddPolicy("controller_cors", policy =>{policy.WithOrigins("http://localhost:5500", "http://localhost:8099");});options.AddPolicy("action_cors", policy =>{policy.WithOrigins("http://localhost:5500", "http://localhost:8099");});});services.AddControllers().AddJsonOptions(options =>{options.JsonSerializerOptions.Converters.Add(new StringJsonConverter());}); }// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseRouting();app.UseCors();app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapControllers();}); }

在上面的代碼中,因?yàn)?EnableCorsAttribute 可以應(yīng)用到類和屬性上,所以我們定義了兩個(gè) CORS 策略,分別是 controllercors 和 actioncors。接下來將這兩種策略應(yīng)用到 WeatherForecastController 上。

應(yīng)用 EnableCorsAttribute 特性標(biāo)記

[ApiController] [Route("[controller]")] [EnableCors("controller_cors")] public class WeatherForecastController : ControllerBase {[EnableCors("action_cors")][HttpPost]public string Users(){return "Users";}[DisableCors][HttpGet]public string List(){return "List";}[HttpGet]public string Index(){return "Index";} }

在上面的 WeatherForecastController 控制器中,我們將 controllercors 標(biāo)記到控制器上,將 actioncors 標(biāo)記到 Action 名稱為 Users 上面,同時(shí),還對 List 應(yīng)用了 DisableCors ,表示對 List 禁用 CORS 的策略,所以我們知道,在 CORS 中,有 AddCors/UseCors,也有 EnableCors/DisableCors ,都是成對出現(xiàn)的。

其它策略

我們還記得,在 .NETCore 中,一共有 4 種策略,分別是:Header、Method、Origin、Credentials,但是本文僅演示了 WithOrigins 這一種方式,相信通過這一種方式的演示,對大家在啟用其它策略的時(shí)候,其思想也是一致的,所謂的標(biāo)頭、請求方式、憑據(jù) 等等,其基本法是不變的。

通過對 Microsoft.AspNetCore.Cors 的內(nèi)部實(shí)現(xiàn)的剖析,我們了解到,其實(shí)現(xiàn) CORS 的原理非常簡單,結(jié)構(gòu)清晰,就算不用系統(tǒng)自帶的 CORS 組件,自行實(shí)現(xiàn)一個(gè) CORS 策略,也是非常容易的。

參考資料:(CORS) 啟用跨域請求 ASP.NET Core

GitHub:https://github.com/dotnet/aspnetcore/tree/master/src/Mvc/Mvc/src https://github.com/dotnet/aspnetcore/tree/master/src/Mvc/Mvc.Cors/src https://github.com/dotnet/aspnetcore/tree/master/src/Middleware/CORS/src

總結(jié)

以上是生活随笔為你收集整理的深入剖析.NETCORE中CORS(跨站资源共享)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。