调用Login方法时AccountController抛出HS256密钥长度异常
解决ASP.NET Core 6中JWT HS256算法密钥长度不足的异常
我正在阅读一本基于ASP.NET Core 6的书籍,目前内容都不错,但在学习身份认证与授权章节时遇到了异常。
AccountController中的Register方法可正常将用户记录写入SQL的AspNetUsers表,但调用Login方法时抛出如下异常:
System.ArgumentOutOfRangeException: 'IDX10720: Unable to create KeyedHashAlgorithm for algorithm 'HS256', the key size must be greater than: '256' bits, key has '216' bits
相关代码
namespace MyBGList.Controllers { [Route("[controller]/[action]")] [ApiController] public class AccountController : ControllerBase { private readonly ApplicationDbContext _context; private readonly ILogger<AccountController> _logger; private readonly IConfiguration _configuration; private readonly UserManager<ApiUser> _userManager; private readonly SignInManager<ApiUser> _signInManager; public AccountController(ApplicationDbContext context, ILogger<AccountController> logger, IConfiguration configuration, UserManager<ApiUser> userManager, SignInManager<ApiUser> signInManager) { _context = context; _logger = logger; _configuration = configuration; _userManager = userManager; _signInManager = signInManager; } //[ResponseCache(CacheProfileName = "NoCache")] [HttpPost] public async Task<ActionResult> Register(RegisterDTO input) { try { if (ModelState.IsValid) { var newUser = new ApiUser(); newUser.UserName = input.UserName; newUser.Email = input.Email; var result = await _userManager.CreateAsync(newUser, input.Password); if (result.Succeeded) { _logger.LogInformation("User {userName} ({email}) has been created.", newUser.UserName, newUser.Email); return StatusCode(201,$"User '{newUser.UserName}' has been created."); } else throw new Exception(string.Format("Error: {0}", string.Join(" ", result.Errors.Select(e => e.Description)))); } else { var details = new ValidationProblemDetails(ModelState); details.Type = "https://tools.ietf.org/html/rfc7231#section-6.5.1"; details.Status = StatusCodes.Status400BadRequest; return new BadRequestObjectResult(details); } } catch (Exception e) { var exceptionDetails = new ProblemDetails(); exceptionDetails.Detail = e.Message; exceptionDetails.Status = StatusCodes.Status500InternalServerError; exceptionDetails.Type = "https://tools.ietf.org/html/rfc7231#section-6.6.1"; return StatusCode(StatusCodes.Status500InternalServerError, exceptionDetails); } } //[ResponseCache(CacheProfileName = "NoCache")] [HttpPost] public async Task<ActionResult> Login(LoginDTO input) { try { if (ModelState.IsValid) { var user = await _userManager.FindByNameAsync(input.UserName); if (user == null || !await _userManager.CheckPasswordAsync(user, input.Password)) { throw new Exception("Invalid login attempt."); } else { var signingCredentials = new SigningCredentials( new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:SigningKey"])), SecurityAlgorithms.HmacSha256); var claims = new List<Claim>(); claims.Add(new Claim(ClaimTypes.Name, user.UserName)); var jwtObject = new JwtSecurityToken(issuer: _configuration["JWT:Issuer"], audience: _configuration["JWT:Audience"], claims: claims, expires: DateTime.Now.AddSeconds(300), signingCredentials: signingCredentials); // 此处抛出异常 var jwtString = new JwtSecurityTokenHandler().WriteToken(jwtObject); return StatusCode(StatusCodes.Status200OK, jwtString); } } else { var details = new ValidationProblemDetails(ModelState); details.Type = "https://tools.ietf.org/html/rfc7231#section-6.5.1"; details.Status = StatusCodes.Status400BadRequest; return new BadRequestObjectResult(details); } } catch (Exception e) { var exceptionDetails = new ProblemDetails(); exceptionDetails.Detail = e.Message; exceptionDetails.Status = StatusCodes.Status401Unauthorized; exceptionDetails.Type = "https://tools.ietf.org/html/rfc7231#section-6.6.1"; return StatusCode(StatusCodes.Status401Unauthorized, exceptionDetails); } } } }
机密文件内容
{ "ConnectionStrings": { "DefaultConnection": "Server=MyServer\\SQLEXPRESS;Database=MyBGList;User Id=MyBGListUser;Password=happy;Integrated Security=False;MultipleActiveResultSets=True; TrustServerCertificate=True" }, "JWT": { "Issuer": "MyBGList", "Audience": "MyBGList", "SigningKey": "MyVeryOwnTestSigningKey123$" } }
问题原因及解决方案
原因
异常提示明确说明:HS256(HMAC-SHA256)算法要求密钥长度至少为256位(32字节),而当前使用的密钥MyVeryOwnTestSigningKey123$经UTF-8编码后仅27字节(216位),不满足算法最低要求。
解决步骤
生成符合要求的密钥
可通过以下方式生成32字节的随机密钥:- 使用在线随机字符串生成工具,选择32长度的字符串(或Base64编码的32字节数据)
- 在PowerShell中执行命令:
[Convert]::ToBase64String([System.Security.Cryptography.RandomNumberGenerator]::GetBytes(32)) - 在.NET代码中生成:
var keyBytes = new byte[32]; using var rng = System.Security.Cryptography.RandomNumberGenerator.Create(); rng.GetBytes(keyBytes); var signingKey = Convert.ToBase64String(keyBytes);
更新配置文件
将机密文件中的JWT:SigningKey替换为新生成的密钥,示例:"JWT": { "Issuer": "MyBGList", "Audience": "MyBGList", "SigningKey": "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP" // 32字节示例密钥 }重启应用并测试
重启ASP.NET Core应用后,重新调用Login接口即可正常生成JWT令牌。
额外建议
生产环境中请勿将密钥明文存储在配置文件,建议使用:
- Azure Key Vault、AWS Secrets Manager等云服务密钥管理工具
- 本地操作系统机密管理器(如Windows Credential Manager、Linux Vault)
内容的提问来源于stack exchange,提问作者CoderForHire
相关产品推荐
相关产品推荐

