所有控制器中HttpContext.User始终为null的技术求助
问题描述
在任意控制器中执行var usr = User as ClaimsPrincipal;,结果始终为null。已完成的应用配置如下:
var builder = WebApplication.CreateBuilder(args); ConfigurationManager configuration = builder.Configuration; builder.Services.AddDbContext<CustomIdentityDbContext>(options => { options.UseSqlServer(configuration.GetConnectionString("SqlServerConnection")).EnableSensitiveDataLogging(); } ); //配置自定义身份验证 builder.Services.AddIdentity<WSA_UTENTE, WSA_RUOLI>(options => { options.SignIn.RequireConfirmedAccount = true; }) .AddEntityFrameworkStores<CustomIdentityDbContext>() .AddDefaultTokenProviders(); //添加JWT认证中间件 builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = 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"])) }; });
能够成功生成Token,生成方法如下:
private JwtSecurityToken GetToken(IEnumerable<Claim> authClaims) { var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"])); var token = new JwtSecurityToken( issuer: _configuration["Jwt:ValidIssuer"], audience: _configuration["Jwt:ValidAudience"], expires: DateTime.Now.AddMinutes(String.IsNullOrEmpty(_configuration["Jwt:AccessTokenLifetime"]) ? int.Parse(_configuration["Jwt:AccessTokenLifetime"]) : 525600), claims: authClaims, signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256) ); return token; }
Token包含的主要Claims:
"sub: 8001ac54-12c0-4d18-f5a7-08db0445001d" "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: myusername"
疑问:是否需要调用HttpContext.SignInAsync来填充HttpContext.User,还是JWT中间件会自动完成该操作?
问题分析与解决
核心结论
JWT认证中间件会自动解析请求头中的有效Token并填充HttpContext.User,不需要调用HttpContext.SignInAsync(该方法是Cookie认证流程的环节,和JWT无关)。你的问题大概率出在以下几个环节:
排查点1:中间件顺序错误
必须保证中间件的执行顺序正确:
var app = builder.Build(); // 其他中间件(如静态文件) app.UseStaticFiles(); app.UseRouting(); // 必须在UseRouting之后、UseAuthorization之前添加 app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
如果UseAuthentication()顺序不对,认证逻辑不会触发,User会保持null。
排查点2:请求未携带有效Token
调用接口时,必须在请求头中添加Authorization字段,格式为:
Authorization: Bearer <你的JWT Token字符串>
没有携带该头的话,JWT中间件不会执行解析逻辑。
排查点3:Token配置不匹配
检查生成Token和验证Token的配置项是否一致:
- 生成Token用的是
_configuration["Jwt:ValidIssuer"]和_configuration["Jwt:ValidAudience"] - 验证时用的是
builder.Configuration["Jwt:Issuer"]和builder.Configuration["Jwt:Audience"]
如果配置文件中这两组键名不一致,会导致Token验证失败,User无法被填充。
排查点4:控制器未添加授权特性
确保目标控制器或Action上添加了[Authorize]特性:
[Authorize] public class YourController : ControllerBase { // ... }
没有该特性的话,认证逻辑不会被触发,User会保持默认空状态。
调试验证
可以在请求管道中添加调试代码,确认认证状态:
app.Use(async (context, next) => { Console.WriteLine($"用户是否已认证:{context.User.Identity.IsAuthenticated}"); await next(); });
将这段代码放在UseAuthentication()之后,运行程序调用接口,查看控制台输出,判断认证是否生效。
内容的提问来源于stack exchange,提问作者pinale
相关产品推荐
相关产品推荐

