Angular与.NET8 API跨域问题:非GET请求失败,需兼容Windows身份验证
解决Angular + .NET 8中CORS与Windows身份验证共存问题
问题现象
- GET请求正常,POST/PUT/DELETE请求触发CORS错误,浏览器提示预飞行请求未通过Access-Control检查
- 两种启动配置存在矛盾:
- "SKWangular"配置:跨域正常,但Windows身份验证不生效(
HttpContext.User.Identity.IsAuthenticated返回false) - "IIS Express"配置:Windows身份验证正常,但非GET请求均报CORS错误
- "SKWangular"配置:跨域正常,但Windows身份验证不生效(
核心原因
非GET请求会发送OPTIONS预飞行请求,Windows身份验证默认会拦截匿名的OPTIONS请求,导致CORS响应头无法返回;同时中间件顺序、CORS策略的细节配置也可能存在冲突。
分步解决方案
1. 修正中间件执行顺序
确保CORS中间件优先于身份验证、端点路由执行,CookiePolicy中间件放在CORS之后、身份验证之前:
// Program.cs 中间件顺序调整后 Middleware.HttpsRedirection.Apply(app); Middleware.Routing.Apply(app); Middleware.Cors.Apply(app); // 必须在Authentication和Endpoints之前 Middleware.CookiePolicy.Apply(app); Middleware.Authentication.Apply(app); Middleware.Endpoints.Apply(app);
2. 允许OPTIONS请求匿名访问
Windows身份验证会拦截OPTIONS预飞行请求,需要单独配置让OPTIONS请求跳过身份验证:
// Program.cs 中添加授权策略配置 services.AddAuthorization(options => { // 默认要求所有请求身份验证 options.FallbackPolicy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .Build(); // 添加匿名访问策略 options.AddPolicy("AllowAnonymous", policy => policy.AllowAnonymous()); }); // 在端点路由中配置OPTIONS请求允许匿名 app.UseEndpoints(endpoints => { // 处理所有API路径的OPTIONS请求 endpoints.Map("api/{**path}", context => { if (context.Request.Method.Equals(HttpMethod.Options.Method, StringComparison.OrdinalIgnoreCase)) { // 返回CORS所需响应头 context.Response.Headers.Add("Access-Control-Allow-Origin", context.Request.Headers["Origin"]); context.Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); context.Response.Headers.Add("Access-Control-Allow-Headers", context.Request.Headers["Access-Control-Request-Headers"]); context.Response.Headers.Add("Access-Control-Allow-Credentials", "true"); context.Response.StatusCode = StatusCodes.Status200OK; } return Task.CompletedTask; }).AllowAnonymous(); endpoints.MapControllers().RequireAuthorization(); });
3. 优化CORS策略配置
确保CORS策略与AllowCredentials兼容,避免冲突:
services.AddCors(options => { options.AddPolicy("_myAllowSpecificOrigins", builder => { builder.WithOrigins("https://localhost:44498", "https://localhost:44337") .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); });
注意:不要同时使用
AllowAnyOrigin和AllowCredentials,这会触发浏览器CORS规则冲突。
4. 调整IIS Express配置(针对IIS Express启动项)
在项目根目录添加web.config,配置IIS允许匿名OPTIONS请求并返回CORS头:
<configuration> <system.webServer> <security> <authentication> <windowsAuthentication enabled="true" /> <anonymousAuthentication enabled="true" /> </authentication> </security> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="https://localhost:44498" /> <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" /> <add name="Access-Control-Allow-Headers" value="Content-Type" /> <add name="Access-Control-Allow-Credentials" value="true" /> </customHeaders> </httpProtocol> </system.webServer> </configuration>
5. Angular端全局配置凭证携带
避免在每个请求中重复设置withCredentials,添加HTTP拦截器全局配置:
// auth.interceptor.ts import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http'; @Injectable() export class AuthInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler) { // 克隆请求并添加凭证 const authRequest = req.clone({ withCredentials: true }); return next.handle(authRequest); } } // app.module.ts import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { AuthInterceptor } from './auth.interceptor'; @NgModule({ imports: [HttpClientModule], providers: [ { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true } ] }) export class AppModule { }
内容的提问来源于stack exchange,提问作者Falcon
相关产品推荐
相关产品推荐

