You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 10:57:36