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

ASP.NET Core 8 MVC中通过认证中间件实现登录重定向

ASP.NET Core 8 MVC 实现认证/授权缺失时重定向到登录页

针对你的场景(JWT令牌存于Cookie,带[Authorize]的Action在令牌无效/缺失或特定授权Cookie不存在时重定向到/login),可以通过以下步骤实现:

1. 配置JWT认证中间件(从Cookie读取令牌)

在Program.cs中配置认证服务,指定JWT从Cookie获取,并处理认证失败/未授权时的重定向逻辑:

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    // 配置JWT验证参数
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = builder.Configuration["Jwt:Issuer"],
        ValidAudience = builder.Configuration["Jwt:Audience"],
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
    };

    // 从指定Cookie读取JWT令牌
    options.Events = new JwtBearerEvents
    {
        OnMessageReceived = context =>
        {
            // 替换为你的JWT Cookie名称
            context.Token = context.Request.Cookies["JwtTokenCookie"];
            return Task.CompletedTask;
        },

        // 处理令牌无效/缺失的认证失败场景
        OnAuthenticationFailed = context =>
        {
            // 非API请求才重定向(API可返回401)
            if (!context.Request.Path.StartsWithSegments("/api"))
            {
                context.Response.Redirect("/login");
                context.HandleResponse(); // 终止后续管道处理
            }
            return Task.CompletedTask;
        },

        // 处理未授权的挑战场景
        OnChallenge = context =>
        {
            if (!context.Response.HasStarted && !context.Request.Path.StartsWithSegments("/api"))
            {
                context.Response.Redirect("/login");
                context.HandleResponse();
            }
            return Task.CompletedTask;
        }
    };
});

2. 自定义授权策略检查特定Cookie

如果需要额外检查特定授权Cookie的存在,需自定义授权要求和处理程序:

定义授权要求

public class RequireAuthorizationCookieRequirement : IAuthorizationRequirement
{
    public string CookieName { get; }

    public RequireAuthorizationCookieRequirement(string cookieName)
    {
        CookieName = cookieName;
    }
}

实现授权处理程序

public class RequireAuthorizationCookieHandler : AuthorizationHandler<RequireAuthorizationCookieRequirement>
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public RequireAuthorizationCookieHandler(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RequireAuthorizationCookieRequirement requirement)
    {
        var httpContext = _httpContextAccessor.HttpContext;
        if (httpContext == null)
        {
            context.Fail();
            return Task.CompletedTask;
        }

        // 检查指定授权Cookie是否存在
        if (httpContext.Request.Cookies.ContainsKey(requirement.CookieName))
        {
            context.Succeed(requirement);
        }
        else
        {
            // Cookie不存在时重定向到登录页(非API请求)
            if (!httpContext.Response.HasStarted && !httpContext.Request.Path.StartsWithSegments("/api"))
            {
                httpContext.Response.Redirect("/login");
            }
            context.Fail();
        }

        return Task.CompletedTask;
    }
}

注册授权服务

在Program.cs中添加授权配置并注册处理程序:

// 添加授权服务,自定义策略
builder.Services.AddAuthorization(options =>
{
    // 策略:需已认证+存在指定授权Cookie
    options.AddPolicy("AuthAndCookieRequired", policy =>
    {
        policy.RequireAuthenticatedUser();
        policy.Requirements.Add(new RequireAuthorizationCookieRequirement("AuthorizationCookie"));
    });

    // 可选:将此策略设为全局默认,所有[Authorize]自动应用
    // options.DefaultPolicy = options.GetPolicy("AuthAndCookieRequired")!;
});

// 注册自定义授权处理程序
builder.Services.AddSingleton<IAuthorizationHandler, RequireAuthorizationCookieHandler>();
// 确保注册HttpContextAccessor(用于在授权处理程序中访问HttpContext)
builder.Services.AddHttpContextAccessor();

3. 在Action上应用授权策略

在需要保护的Action上添加[Authorize]特性,指定自定义策略:

[Authorize(Policy = "AuthAndCookieRequired")]
public IActionResult ProtectedPage()
{
    return View();
}

4. 确保中间件顺序正确

在Program.cs的管道配置中,认证和授权中间件必须按以下顺序添加:

app.UseAuthentication();
app.UseAuthorization();

// 其他中间件(如路由、静态文件等)放在合适位置
app.UseRouting();
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

关键说明

  • 区分API和MVC请求:代码中加入了!context.Request.Path.StartsWithSegments("/api")判断,确保API请求返回401而非重定向,根据你的实际路由调整该判断逻辑。
  • Cookie名称替换:将代码中的JwtTokenCookie和AuthorizationCookie替换为你实际使用的Cookie名称。
  • 全局策略:如果希望所有[Authorize]都自动应用该规则,取消options.DefaultPolicy的注释即可。

内容的提问来源于stack exchange,提问作者coach_rob

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 19:20:15