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

ASP.NET Core中过期令牌仍触发自定义AuthorizationHandler是否正常?

ASP.NET Core 6自定义AuthorizationHandler遇过期令牌仍触发的问题解答

这是预期行为。ASP.NET Core的认证(Authentication)与授权(Authorization)是两个独立执行的阶段:

  • 当令牌过期时,认证阶段会标记当前用户为未认证,但不会直接终止请求流程;
  • 请求会继续进入授权阶段,因此你自定义的AuthorizationHandler依然会被触发执行。

你遇到的声明不存在问题,核心原因是服务构造函数的执行时机不对:构造函数在AuthorizationHandler初始化时就会被调用,此时请求上下文还未完全初始化,或者因令牌过期导致认证失败,ClaimsPrincipal为空/无有效声明。直接在构造函数中读取请求级别的用户声明本身就是不合理的设计。

解决办法

  1. 调整服务设计,延迟读取声明
    不要在服务构造函数中依赖用户声明,改为在方法内部通过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;
            }
        }
    }
    
  2. 在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;
    }
    
  3. 让认证中间件提前终止过期令牌请求
    如果希望过期令牌的请求直接返回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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 01:34:53