ASP.NET Core中过期令牌仍触发自定义AuthorizationHandler是否正常?
这是预期行为。ASP.NET Core的认证(Authentication)与授权(Authorization)是两个独立执行的阶段:
- 当令牌过期时,认证阶段会标记当前用户为未认证,但不会直接终止请求流程;
- 请求会继续进入授权阶段,因此你自定义的
AuthorizationHandler依然会被触发执行。
你遇到的声明不存在问题,核心原因是服务构造函数的执行时机不对:构造函数在AuthorizationHandler初始化时就会被调用,此时请求上下文还未完全初始化,或者因令牌过期导致认证失败,ClaimsPrincipal为空/无有效声明。直接在构造函数中读取请求级别的用户声明本身就是不合理的设计。
解决办法
调整服务设计,延迟读取声明
不要在服务构造函数中依赖用户声明,改为在方法内部通过IHttpContextAccessor获取当前请求的用户信息:public class YourService { private readonly IHttpContextAccessor _httpContextAccessor; public YourService(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } public void ProcessClaims() { var user = _httpContextAccessor.HttpContext?.User; if (user?.Identity?.IsAuthenticated == true) { // 在这里读取并处理声明 var userId = user.FindFirst(ClaimTypes.NameIdentifier)?.Value; } } }在AuthorizationHandler中提前拦截未认证请求
在HandleRequirementAsync方法开头先判断用户认证状态,未认证时直接终止授权逻辑:protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, YourCustomRequirement requirement) { // 未认证直接返回失败 if (!context.User.Identity.IsAuthenticated) { context.Fail(); return Task.CompletedTask; } // 执行你的授权逻辑 context.Succeed(requirement); return Task.CompletedTask; }让认证中间件提前终止过期令牌请求
如果希望过期令牌的请求直接返回401,不进入授权阶段,可以在JWT认证配置中添加事件处理:builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.Events = new JwtBearerEvents { OnAuthenticationFailed = context => { if (context.Exception is SecurityTokenExpiredException) { context.Response.StatusCode = StatusCodes.Status401Unauthorized; context.Response.ContentType = "application/json"; // 可自定义返回内容 var response = JsonSerializer.Serialize(new { message = "令牌已过期" }); return context.Response.WriteAsync(response); } return Task.CompletedTask; } }; // 其他JWT配置(如密钥、验证参数等) }); }
内容的提问来源于stack exchange,提问作者V K
相关产品推荐
相关产品推荐

