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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 01:27:04