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

.NET Core应用中HttpContext.User未填充,User.GetUserId()返回0问题

问题描述

调用User.GetUserId()始终返回0,且User.IsAuthenticated = false。Postman和Angular客户端均能成功获取Token,请求时也已将Token添加到请求头的Authorization字段(格式为Bearer <token>),但调用包含User.GetUserId()的其他接口时仍得到相同结果。

更新TokenService后,登录控制器中调用CreateToken方法后能从User获取正确ID,但其他接口的HttpContext.User仍为空(已注入IHttpContextAccessor)。


相关代码

Startup.cs 的 Configure 方法

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseRouting();
  
    app.UseCors(x => x
            .AllowAnyHeader()
            .AllowAnyMethod()
            .AllowAnyOrigin()
            .AllowCredentials()
            .WithOrigins("https://localhost:4200"));

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapFallbackToController("Index", "Fallback");
    });
}

AccountController 的 Login 方法

[HttpPost("login")]
public async Task<ActionResult<UserDto>> Login(LoginDto loginDto)
{
    var user = await _userManager.Users
                                 .Include(p => p.Photos)
                                 .SingleOrDefaultAsync(x => x.UserName == loginDto.Username.ToLower());

    if (user == null) 
        return Unauthorized("Invalid username");

    var result = await _signInManager
                           .CheckPasswordSignInAsync(user, loginDto.Password, false);
 
    if (!result.Succeeded) 
        return Unauthorized();

    var token = await _tokenService.CreateToken(user);

    var userDto = new UserDto
        {
            Username = user.UserName,
            Token = token,
            KnownAs = user.KnownAs,
            Gender = user.Gender
        };

    var uId = User.GetUserId(); // 此处返回0

    return userDto;
}

TokenService.cs

public class TokenService : ITokenService
{
    private readonly SymmetricSecurityKey _key;
    private readonly UserManager<AppUser> _userManager;
    private readonly IHttpContextAccessor _httpContextAccessor; // 更新后新增注入

    public TokenService(IConfiguration config, UserManager<AppUser> userManager, IHttpContextAccessor httpContextAccessor)
    {
        _userManager = userManager;
        _key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["TokenKey"]));
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task<string> CreateToken(AppUser user)
    {
        var claims = new List<Claim>
                         {
                             new Claim(JwtRegisteredClaimNames.NameId, user.Id.ToString()),
                             new Claim(JwtRegisteredClaimNames.UniqueName, user.UserName.ToString())
                         };

        var roles = await _userManager.GetRolesAsync(user);

        claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role)));

        var creds = new SigningCredentials(_key, SecurityAlgorithms.HmacSha512Signature);

        var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(claims),
                Expires = DateTime.Now.AddDays(7),
                SigningCredentials = creds
            };

        // UPDATE: 手动设置HttpContext.User的代码
        var identity = new ClaimsIdentity(claims);
        var claimsPrincipal = new ClaimsPrincipal(identity);
        _httpContextAccessor.HttpContext.User = claimsPrincipal;


        var tokenHandler = new JwtSecurityTokenHandler();

        var token = tokenHandler.CreateToken(tokenDescriptor);

        return tokenHandler.WriteToken(token);
    }
}

问题分析与解决方案

1. Login接口中User.GetUserId()返回0的原因

登录请求本身未经过认证流程,此时User对象还未被认证中间件填充,所以无法获取到用户ID。直接使用查询到的user.Id即可,无需通过User对象获取。

修改Login方法中的代码:

// 替换原代码
var uId = user.Id;

2. 其他接口User.IsAuthenticated = false的核心问题

你的项目缺少JWT认证方案的配置,仅调用app.UseAuthentication()不足以让系统自动解析请求头中的Bearer Token,导致认证失败,User始终处于未认证状态。

解决步骤:

在Startup.cs的ConfigureServices方法中添加JWT认证配置:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;

// ...

public void ConfigureServices(IServiceCollection services)
{
    // 其他服务配置...

    // 添加JWT认证
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                // 确保此处的TokenKey与TokenService中使用的一致
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["TokenKey"])),
                ValidateIssuer = false, // 根据你的需求调整,若有签发方则设置为true并配置ValidIssuer
                ValidateAudience = false // 根据你的需求调整,若有受众则设置为true并配置ValidAudience
            };
        });

    // 其他服务配置...
}

3. TokenService中手动设置HttpContext.User的错误

手动设置HttpContext.User仅对当前登录请求生效,后续请求的上下文是独立的,这一操作完全多余且会导致逻辑混乱。删除这部分代码:

// 删掉以下代码
var identity = new ClaimsIdentity(claims);
var claimsPrincipal = new ClaimsPrincipal(identity);
_httpContextAccessor.HttpContext.User = claimsPrincipal;

4. 验证中间件顺序

你的Configure方法中中间件顺序是正确的,保持以下顺序即可:
UseRouting → UseCors → UseAuthentication → UseAuthorization → UseEndpoints

5. 测试注意事项

确保请求头的Authorization格式完全正确:Bearer <token>,Token前后无多余空格,且Token是完整有效的。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 09:26:08