Asp.net Core 6中Cookie认证请求未跳转登录页,返回401问题
问题分析与解决方案
核心问题原因
你的配置中把DefaultChallengeScheme全局设置为了JwtBearer的Scheme,而JwtBearer认证处理器在处理未授权请求时,默认会返回401状态码,不会触发Cookie认证的重定向逻辑。即便你配置了Cookie的LoginPath,只要默认挑战Scheme是JwtBearer,就会优先执行Jwt的处理逻辑,导致重定向失效。
另外,自定义CustomCookieAuthenticationEvents里的context.Response.StatusCode == StatusCodes.Status200OK判断逻辑不合理——重定向场景下响应状态码默认是302,这个分支根本不会触发,进一步加剧了问题。
修复步骤
1. 调整认证默认Scheme配置
移除全局默认挑战Scheme的硬编码,改为根据请求类型动态选择:
builder.AddAuthentication(options => { options.DefaultScheme = IdentityConstants.ApplicationScheme; // 删掉原DefaultChallengeScheme的JwtBearer设置 }) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { options.IncludeErrorDetails = true; options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateLifetime = true, ValidIssuer = FlymarkAppSettings.Instance.JwtTokenIssuer, ValidAudience = FlymarkAppSettings.Instance.JwtTokenAudience, ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(FlymarkAppSettings.Instance.JwtTokenSigningKey)) }; })
2. 添加动态Scheme路由
通过AddPolicyScheme实现请求路径的动态判断,自动切换认证逻辑:
builder.AddAuthentication(options => { options.DefaultScheme = "DynamicScheme"; options.DefaultChallengeScheme = "DynamicScheme"; }) .AddPolicyScheme("DynamicScheme", "Dynamic Scheme", options => { options.ForwardDefaultSelector = context => { // API路径用JwtBearer,页面请求用Cookie认证 return context.Request.Path.StartsWithSegments("/api") ? JwtBearerDefaults.AuthenticationScheme : IdentityConstants.ApplicationScheme; }; }) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { // 保留原JWT配置不变 })
3. 修正自定义CookieEvents逻辑
去掉多余的状态码判断,同时清空重定向头避免响应矛盾:
public class CustomCookieAuthenticationEvents : CookieAuthenticationEvents { public override Task RedirectToLogin(RedirectContext<CookieAuthenticationOptions> context) { if (context.Request.Path.StartsWithSegments("/api")) { context.Response.StatusCode = StatusCodes.Status401Unauthorized; context.Response.Headers.Remove("Location"); return Task.CompletedTask; } return base.RedirectToLogin(context); } public override Task RedirectToAccessDenied(RedirectContext<CookieAuthenticationOptions> context) { if (context.Request.Path.StartsWithSegments("/api")) { context.Response.StatusCode = StatusCodes.Status403Forbidden; context.Response.Headers.Remove("Location"); return Task.CompletedTask; } return base.RedirectToAccessDenied(context); } }
4. 更新授权策略
将授权策略的认证Scheme改为动态Scheme:
builder.AddAuthorization(options => { options.DefaultPolicy = new AuthorizationPolicyBuilder() .AddAuthenticationSchemes("DynamicScheme") .RequireAuthenticatedUser() .Build(); });
验证效果
- 前端页面未认证请求:自动重定向到
/Identity/Account/LogIn(返回302状态码) - API未认证请求:直接返回401状态码,无重定向头
内容的提问来源于stack exchange,提问作者Vova Bilyachat
相关产品推荐
相关产品推荐

