如何在ASP.NET Core中用AuthorizationHandler处理未授权API调用并返回401
解决ASP.NET Core 8 API授权失败返回302而非401/403的问题
问题核心是ASP.NET Core默认身份验证/授权中间件为MVC场景设计,会自动重定向到登录或AccessDenied页面,而API端点需要返回标准HTTP状态码给Angular客户端。以下是具体解决步骤:
1. 拦截Cookie认证的重定向行为
在配置Cookie认证时,判断请求是否为API请求(通过路径或Accept头),如果是则直接返回对应状态码,而非重定向:
builder.Services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddCookie(options => { // 处理未登录的重定向 options.Events.OnRedirectToLogin = context => { if (IsApiRequest(context.Request)) { context.Response.StatusCode = StatusCodes.Status401Unauthorized; return Task.CompletedTask; } context.Response.Redirect(context.RedirectUri); return Task.CompletedTask; }; // 处理权限不足的重定向 options.Events.OnRedirectToAccessDenied = context => { if (IsApiRequest(context.Request)) { context.Response.StatusCode = StatusCodes.Status403Forbidden; return Task.CompletedTask; } context.Response.Redirect(context.RedirectUri); return Task.CompletedTask; }; }) .AddOpenIdConnect(options => { // 你的OIDC基础配置(Authority、ClientId等) options.Authority = "你的OIDC授权地址"; options.ClientId = "你的客户端ID"; options.ClientSecret = "你的客户端密钥"; options.ResponseType = OpenIdConnectResponseType.Code; // 拦截OIDC的重定向请求 options.Events.OnRedirectToIdentityProvider = context => { if (IsApiRequest(context.Request)) { context.Response.StatusCode = StatusCodes.Status401Unauthorized; context.HandleResponse(); // 终止后续重定向逻辑 } return Task.CompletedTask; }; }); // 辅助方法:判断是否为API请求 bool IsApiRequest(HttpRequest request) { return request.Path.StartsWithSegments("/api") || request.Headers.Accept.Contains("application/json"); }
2. 自定义授权失败处理器
如果API使用了自定义AuthorizationHandler,可以添加全局授权失败处理器,确保API场景下返回正确状态码:
实现授权失败处理器
public class ApiAuthorizationFailureHandler : IAuthorizationFailureHandler { public Task HandleAsync(AuthorizationHandlerContext context) { var httpContext = context.Resource as HttpContext; if (httpContext != null && IsApiRequest(httpContext.Request)) { httpContext.Response.StatusCode = context.User.Identity.IsAuthenticated ? StatusCodes.Status403Forbidden : StatusCodes.Status401Unauthorized; } return Task.CompletedTask; } private bool IsApiRequest(HttpRequest request) { return request.Path.StartsWithSegments("/api") || request.Headers.Accept.Contains("application/json"); } }
注册处理器
builder.Services.AddScoped<IAuthorizationFailureHandler, ApiAuthorizationFailureHandler>();
3. 配置API专属授权策略
在授权配置中,为API端点指定专属策略,确保使用自定义失败处理器:
builder.Services.AddAuthorization(options => { options.AddPolicy("ApiPolicy", policy => { policy.RequireAuthenticatedUser(); policy.AddRequirements(new YourCustomRequirement()); // 你的自定义权限要求 policy.FailureHandler = new ApiAuthorizationFailureHandler(); }); });
然后在极简API端点上应用该策略:
app.MapGet("/api/your-endpoint", () => Results.Ok("内容")) .RequireAuthorization("ApiPolicy");
关键说明
- 区分API和MVC请求:通过路径前缀(如
/api)或Accept头判断,保证MVC页面仍能正常重定向到登录/拒绝页面,API则返回状态码。 - 终止重定向逻辑:在OIDC事件中调用
context.HandleResponse()可以阻止后续的重定向流程,直接返回状态码。
内容的提问来源于stack exchange,提问作者Andrew HB
相关产品推荐
相关产品推荐

