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
相关产品推荐
相关产品推荐

