使用JwtBearer时自定义AuthorizeAttribute中HttpContext.Items["User"]为空的问题求助
问题分析与修复方案
核心问题
你的代码存在两个关键错误:
- 自定义的
AuthorizeAttribute与ASP.NET Core框架自带的[Authorize]特性重名,导致框架的JWT/OIDC认证逻辑完全未触发——Bearer令牌根本没被解析,自然不会生成用户身份信息。 - 即便框架认证正常执行,用户身份信息也不会存储在
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();
验证逻辑
修复后,请求流程变为:
- 框架的JWT认证中间件解析Bearer令牌,验证合法性后生成
HttpContext.User - 自定义的
CustomAuthorizeAttribute检查用户已认证,从ClaimsPrincipal提取信息转换为User对象并存入HttpContext.Items - 接口正常执行,可从
HttpContext.Items获取到User对象
内容的提问来源于stack exchange,提问作者jie xiao
相关产品推荐
相关产品推荐

