ASP.NET Core自定义BCrypt密码哈希器登录报Base64无效格式异常
问题根因定位
你现在的实现存在哈希生成逻辑与校验逻辑完全不匹配的问题,直接触发了Base64格式解析异常:
- 校验方法
VerifyHashedPassword设计了固定解析流程:收到哈希字符串后第一时间调用Convert.FromBase64String将其转为字节数组,再通过首字节标记区分哈希类型(自定义BCrypt用0xFF标记、默认PBKDF2走基类校验)。 - 但哈希生成方法
HashPassword直接返回了BCrypt组件原生的输出字符串,这类字符串包含$、.等非Base64字符,完全不符合校验端的Base64格式要求,自然会在解析环节抛出格式异常。 - 注册流程能正常完成是因为
HashPassword没有入参格式校验,只要拿到字符串就直接写入数据库;但登录走校验流程时,硬解析非Base64字符串的步骤必然触发异常。
修正方案
1. 对齐哈希生成逻辑与校验逻辑
按照你在VerifyHashedPassword中约定的0xFF格式标记规则,重写HashPassword方法,保证生成的存储值能被校验逻辑正常解析:
public override string HashPassword(TUser user, string password) { if (password == null) { throw new ArgumentNullException(nameof(password)); } // 生成原生BCrypt哈希,可通过settings配置计算工作因子 var bcryptRawHash = BCrypt.Net.BCrypt.HashPassword( password, workFactor: _settings?.WorkFactor ?? 11); // 将BCrypt哈希转为UTF8字节数组 var hashBytes = Encoding.UTF8.GetBytes(bcryptRawHash); // 拼接自定义格式标记0xFF var storedBytes = new byte[hashBytes.Length + 1]; storedBytes[0] = 0xFF; Buffer.BlockCopy(hashBytes, 0, storedBytes, 1, hashBytes.Length); // 转为Base64字符串存储,完全匹配校验端的解析规则 return Convert.ToBase64String(storedBytes); }
2. 存量测试数据修正
如果之前已经有用户使用旧的错误逻辑(直接存裸BCrypt字符串)完成了注册,需要将数据库中已存在的这类哈希值按照上述封装规则批量修正,否则这些存量用户登录时依然会触发Base64解析错误。
3. 可选优化
当前VerifyHashedPassword中可以补充兼容逻辑:如果校验时发现是默认PBKDF2格式的老哈希,校验通过后同样返回PasswordVerificationResult.SuccessRehashNeeded,实现老用户密码的无感知渐进式迁移,不需要用户手动修改密码就能自动升级为BCrypt格式的存储值。
注意:不要为了规避Base64异常直接删掉
Convert.FromBase64String这行代码,否则会破坏对ASP.NET Core Identity默认PBKDF2格式哈希的兼容能力,导致原有老系统的用户无法正常登录。
内容的提问来源于stack exchange,提问作者Pawara Siriwardhane
相关产品推荐
相关产品推荐

