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

ASP.NET Core中HttpContext.User始终返回空的问题求助

解决ASP.NET Core中HttpContext.User始终为空的问题

可能的原因及对应解决方案


1. 未正确配置JWT认证中间件

确保在Program.cs中正确注册JWT认证服务,并严格遵循中间件顺序:

注册JWT服务:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            // 必须与生成Token时使用的参数完全一致
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes(builder.Configuration["Jwt:SecretKey"])
            )
        };
    });

中间件顺序(核心要求):
UseAuthentication必须在UseAuthorization之前执行,且位于路由配置之后:

app.UseRouting();
app.UseAuthentication(); // 先执行认证逻辑
app.UseAuthorization();  // 再执行授权逻辑
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});

2. 生成AccessToken时未包含用户ID(NameIdentifier)Claim

你的登录代码依赖_userManager.GetClaimsAsync(user)获取Claims,但默认情况下用户不会自动携带NameIdentifier(用户ID)Claim,需手动添加:

修改Login方法的Claims收集逻辑:

// 先构建基础Claims列表,确保包含用户ID
var claims = new List<Claim>
{
    new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
    new Claim(ClaimTypes.Email, user.Email),
    new Claim(ClaimTypes.Name, user.UserName)
};
// 追加用户已有的自定义Claims
claims.AddRange(await _userManager.GetClaimsAsync(user));

// 生成AccessToken
var accessToken = _jwtHandler.GenerateAccessToken(claims);

同时确保GenerateAccessToken方法正确将Claims写入JWT Payload:

public string GenerateAccessToken(IEnumerable<Claim> claims)
{
    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:SecretKey"]));
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

    var token = new JwtSecurityToken(
        issuer: _configuration["Jwt:Issuer"],
        audience: _configuration["Jwt:Audience"],
        claims: claims,
        expires: DateTime.UtcNow.AddMinutes(30),
        signingCredentials: creds);

    return new JwtSecurityTokenHandler().WriteToken(token);
}

3. 未在控制器/Action上添加[Authorize]属性

如果CreatePost方法所在的控制器或Action未标记[Authorize],ASP.NET Core不会触发认证流程,HttpContext.User必然为空。

给目标控制器或Action添加授权属性:

[ApiController]
[Route("api/posts")]
[Authorize] // 整个控制器需认证后访问
public class PostsController : ControllerBase
{
    [HttpPost]
    // 也可单独给该Action添加[Authorize]
    public async Task<IActionResult> CreatePost([FromForm] CreatePostDto createPostDto)
    {
        // 你的业务代码
    }
}

4. 移除不必要的Cookie认证调用

你的登录代码中调用了_signInManager.PasswordSignInAsync,这是Cookie认证的专属方法,与JWT无状态认证逻辑无关,建议移除避免干扰:

修改Login方法:

public async Task<LoginResponseDto> Login(LoginDto loginDto)
{
    var user = _context.Users.FirstOrDefault(e => e.Email == loginDto.Email);
    if (user is null)
        throw new Exception("The user is not valid");

    // 直接验证密码,无需调用Cookie认证方法
    var isPasswordValid = await _userManager.CheckPasswordAsync(user, loginDto.Password);
    if (!isPasswordValid)
    {
        return new LoginResponseDto()
        {
            IsLoginSuccessful = false,
            ErrorMessage = "Invalid Authentication"
        };
    }

    // 收集Claims并生成Token
    var claims = new List<Claim>
    {
        new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
        new Claim(ClaimTypes.Email, user.Email)
    };
    claims.AddRange(await _userManager.GetClaimsAsync(user));

    var accessToken = _jwtHandler.GenerateAccessToken(claims);
    var refreshToken = _jwtHandler.GenerateRefreshToken();
    return new LoginResponseDto() { AccessToken = accessToken, RefreshToken = refreshToken };
}

5. 验证请求中的Token传递是否正确

  • 在Postman/Swagger测试时,必须在请求头中添加Authorization: Bearer <你的AccessToken>
  • 确认Token未过期,且生成时的Issuer、Audience、SecretKey与验证配置完全一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 17:20:22