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

Postman调用API登录时TokenService报ArgumentNullException求助

问题分析与解决方案

错误根源定位

抛出的ArgumentNullException: Value cannot be null. (Parameter 'value')是由于某个必填参数传入null值导致的,结合你的代码和调试信息,可能的触发点有以下几个:

1. 用户核心属性为null

构造Claim时,如果user.UserName或user.Email是null,Claim构造函数会直接抛出该异常——因为Claim的value参数不允许为null。

2. 角色列表包含null元素

你只判断了roles != null,但如果roles列表里存在null的字符串元素,循环到该元素时,new Claim(ClaimTypes.Role, role)同样会触发异常。

3. Token配置项缺失或为空

如果_config["Token:Key"]或_config["Token:Issuer"]未配置或值为空,Encoding.UTF8.GetBytes(null)会直接抛出参数null的异常,后续创建token的流程也会中断。

4. 登录结果判断逻辑无效

_signinManager.CheckPasswordSignInAsync返回的SignInResult是枚举类型,永远不会为null,你当前的if (result == null)判断完全无效,应该用result.Succeeded验证登录是否成功。


修复代码

1. 修正登录端点的判断逻辑

[HttpPost("login")]
public async Task<IActionResult> Login(LoginUser loginData)
{
    var userFromDb = await _userManager.FindByNameAsync(loginData.UserName);

    if (userFromDb == null) return NotFound();

    var result = await _signinManager.CheckPasswordSignInAsync(userFromDb, loginData.Password, false);

    // 替换无效的null判断,改用Succeeded属性验证登录结果
    if (!result.Succeeded) return BadRequest("Invalid Password");

    var roles = await _userManager.GetRolesAsync(userFromDb);

    return Ok(
            new
            {
                result = result,
                username = userFromDb.UserName,
                email = userFromDb.Email,
                token = _tokenService.GenerateToken(userFromDb, roles)
            }
     );
}

2. 完善TokenService的null防护

public class TokenService : ITokenService
{
    private readonly IConfiguration _config;

    public TokenService(IConfiguration config)
    {
        _config = config;
    }

    public string GenerateToken(IdentityUser user, IList<string> roles)
    {
        var claims = new List<Claim>
        {
            // 为用户属性添加null兜底,避免构造Claim时出错
            new Claim(JwtRegisteredClaimNames.GivenName, user.UserName ?? string.Empty),
            new Claim(JwtRegisteredClaimNames.Email, user.Email ?? string.Empty)
        };

        // 过滤roles中的null/空字符串元素
        if (roles != null)
        {
            foreach (var role in roles.Where(r => !string.IsNullOrEmpty(r)))
            {
                claims.Add(new Claim(ClaimTypes.Role, role));
            }
        }

        // 检查Token配置是否存在
        var tokenKey = _config["Token:Key"];
        if (string.IsNullOrEmpty(tokenKey))
        {
            throw new InvalidOperationException("Token:Key 配置项缺失或为空");
        }
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenKey));

        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);

        var issuer = _config["Token:Issuer"];
        if (string.IsNullOrEmpty(issuer))
        {
            throw new InvalidOperationException("Token:Issuer 配置项缺失或为空");
        }

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

        var tokenHandler = new JwtSecurityTokenHandler();
        var token = tokenHandler.CreateToken(tokenDescriptor);

        return tokenHandler.WriteToken(token);
    }
}

额外检查项

  1. 确认appsettings.json中包含有效的Token配置(Key长度建议不低于16位):
{
  "Token": {
    "Key": "your-strong-secret-key-here",
    "Issuer": "your-api-domain"
  }
}
  1. 检查数据库中用户的UserName和Email字段是否存在null值,必要时在注册环节强制要求填写这些信息。

内容的提问来源于stack exchange,提问作者Jean De La Hone

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 01:40:23