.NET Core 3.1 Web API添加自定义中间件后CORS失效如何解决?
问题原因
核心问题有两个:
- 中间件注册顺序错误:
UseCors注册位置晚于自定义校验中间件,跨域预检请求还没完成CORS协商就被自定义中间件拦截返回错误。 - 自定义中间件未放行CORS预检请求:浏览器发起跨域请求前会发送
OPTIONS类型的预检请求,该请求不会携带ApiKey、UserToken这类自定义请求头,直接被校验逻辑拦截返回400错误,导致跨域流程中断。
解决步骤
1. 调整Configure方法中的中间件注册顺序
必须把UseCors放在自定义校验中间件之前,保证跨域协商优先完成,正确的注册顺序如下:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); // 跨域中间件必须放在所有业务校验中间件之前 app.UseCors(builder => { builder.WithOrigins("http://localhost:4200") .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); // 跨域处理完成后再注册自定义校验中间件 app.UseMiddleware<ApiKeyMiddleware>(); app.UseMiddleware<UserTokenMiddleware>(); app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); }); //app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
2. 修改ApiKeyMiddleware,放行预检请求和免校验路径
在校验逻辑前优先放行OPTIONS请求,以及无需校验的/login、/swagger等路径:
public async Task Invoke(HttpContext context, IConfiguration configuration) { // 放行CORS预检请求 if (context.Request.Method.Equals("OPTIONS", StringComparison.OrdinalIgnoreCase)) { await _next.Invoke(context); return; } // 放行无需ApiKey校验的路径 var requestPath = context.Request.Path.Value.ToLower(); if (requestPath.StartsWith("/swagger") || requestPath.StartsWith("/login")) { await _next.Invoke(context); return; } // 原有ApiKey校验逻辑 if (!context.Request.Headers.TryGetValue("ApiKey", out var apiKey) || apiKey != configuration["Security:ApiKey"]) { context.Response.StatusCode = 400; await context.Response.WriteAsync("Invalid request"); return; } await _next.Invoke(context); }
3. 同步修改UserTokenMiddleware
按照同样的逻辑,给UserTokenMiddleware也加上OPTIONS请求放行、免校验路径的逻辑,避免二次拦截导致问题。
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

