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

使用JwtBearer时自定义AuthorizeAttribute中HttpContext.Items["User"]为空的问题求助

问题分析与修复方案

核心问题

你的代码存在两个关键错误:

  1. 自定义的AuthorizeAttribute与ASP.NET Core框架自带的[Authorize]特性重名,导致框架的JWT/OIDC认证逻辑完全未触发——Bearer令牌根本没被解析,自然不会生成用户身份信息。
  2. 即便框架认证正常执行,用户身份信息也不会存储在HttpContext.Items["User"]中,而是保存在HttpContext.User(ClaimsPrincipal类型)里。

修复步骤

1. 重命名自定义授权特性

将自定义的授权特性改名,避免与框架内置特性冲突,确保框架的JWT认证流程能正常执行:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomAuthorizeAttribute : Attribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        // 先检查框架认证是否通过
        if (!context.HttpContext.User.Identity.IsAuthenticated)
        {
            context.Result = new JsonResult(new { message = "Unauthorized" })
            { StatusCode = StatusCodes.Status401Unauthorized };
            return;
        }

        // 从JWT Claims中提取用户信息,转换为自定义User对象
        var userIdClaim = context.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier);
        if (userIdClaim == null)
        {
            context.Result = new JsonResult(new { message = "Invalid token claims" })
            { StatusCode = StatusCodes.Status401Unauthorized };
            return;
        }

        var user = new User
        {
            Id = int.Parse(userIdClaim.Value),
            // 其他属性可从对应Claims中提取,比如用户名、角色等
        };

        // 若需后续接口使用User对象,存入HttpContext.Items
        context.HttpContext.Items["User"] = user;
    }
}

2. 修改Controller的特性使用

同时启用框架的[Authorize](负责JWT令牌解析与身份验证)和自定义的[CustomAuthorize](负责转换为自定义User对象):

[Authorize]
[CustomAuthorize]
[ApiVersion("1.0")]
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
public class UsersController : ControllerBase
{
    [HttpGet]
    public IActionResult GetCurrentUser()
    {
        var user = (User)HttpContext.Items["User"];
        return Ok(user);
    }
}

3. 确保认证中间件配置正确

在Program.cs中正确配置JWT认证服务,并保证中间件顺序(先认证,后授权):

var builder = WebApplication.CreateBuilder(args);

// 添加JWT认证服务
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        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"]))
        };
    });

// 添加授权服务
builder.Services.AddAuthorization();

builder.Services.AddControllers();
builder.Services.AddApiVersioning();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// 中间件顺序不可颠倒:先认证,再授权
app.UseAuthentication();
app.UseAuthorization();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.MapControllers();

app.Run();

验证逻辑

修复后,请求流程变为:

  1. 框架的JWT认证中间件解析Bearer令牌,验证合法性后生成HttpContext.User
  2. 自定义的CustomAuthorizeAttribute检查用户已认证,从ClaimsPrincipal提取信息转换为User对象并存入HttpContext.Items
  3. 接口正常执行,可从HttpContext.Items获取到User对象

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 14:36:07