网站首页 网站源码
namespace Dpz.Core.Service.RepositoryServiceImpl;
/// <summary>
/// 密码哈希服务实现
/// 使用BCrypt作为新版本密码哈希算法,同时兼容旧版本MD5密码
/// </summary>
public class PasswordHashService : IPasswordHashService
{
private const int DefaultWorkFactor = 12;
/// <summary>
/// 使用BCrypt对密码进行哈希(新版本)
/// </summary>
/// <param name="password">原始密码</param>
/// <param name="workFactor">工作因子(默认12)</param>
/// <returns>BCrypt哈希字符串</returns>
public string HashPasswordBCrypt(string password, int workFactor = DefaultWorkFactor)
{
if (string.IsNullOrWhiteSpace(password))
{
throw new ArgumentException("密码不能为空", nameof(password));
}
if (workFactor is < 4 or > 31)
{
throw new ArgumentException("工作因子必须在4-31之间", nameof(workFactor));
}
return BCrypt.Net.BCrypt.HashPassword(password, workFactor);
}
/// <summary>
/// 使用MD5对密码进行哈希(旧版本兼容)
/// </summary>
/// <param name="account">用户账号</param>
/// <param name="password">原始密码</param>
/// <returns>MD5哈希后的密码</returns>
public string HashPasswordMD5(string account, string password)
{
if (string.IsNullOrWhiteSpace(account))
{
throw new ArgumentException("账号不能为空", nameof(account));
}
if (string.IsNullOrWhiteSpace(password))
{
throw new ArgumentException("密码不能为空", nameof(password));
}
var combinedString = account + password;
return combinedString.GenerateMd5();
}
/// <summary>
/// 验证BCrypt密码(新版本)
/// </summary>
/// <param name="password">输入的密码</param>
/// <param name="hashedPassword">存储的BCrypt哈希</param>
/// <returns>密码是否正确</returns>
public bool VerifyPasswordBCrypt(string password, string hashedPassword)
{
if (string.IsNullOrWhiteSpace(password) || string.IsNullOrWhiteSpace(hashedPassword))
{
return false;
}
try
{
return BCrypt.Net.BCrypt.Verify(password, hashedPassword);
}
catch
{
return false;
}
}
/// <summary>
/// 验证MD5密码(旧版本兼容)
/// </summary>
/// <param name="account">用户账号</param>
/// <param name="password">输入的密码</param>
/// <param name="storedHash">存储的MD5哈希</param>
/// <returns>密码是否正确</returns>
public bool VerifyPasswordMD5(string account, string password, string storedHash)
{
if (
string.IsNullOrWhiteSpace(account)
|| string.IsNullOrWhiteSpace(password)
|| string.IsNullOrWhiteSpace(storedHash)
)
{
return false;
}
var expectedHash = HashPasswordMD5(account, password);
return expectedHash.Equals(storedHash, StringComparison.Ordinal);
}
/// <summary>
/// 智能验证密码(自动识别BCrypt或MD5)
/// </summary>
/// <param name="account">用户账号</param>
/// <param name="password">输入的密码</param>
/// <param name="storedHash">存储的密码哈希</param>
/// <returns>密码是否正确</returns>
public bool VerifyPassword(string account, string password, string storedHash)
{
if (string.IsNullOrWhiteSpace(password) || string.IsNullOrWhiteSpace(storedHash))
{
return false;
}
// 如果是BCrypt格式,使用BCrypt验证
if (IsBCryptHash(storedHash))
{
return VerifyPasswordBCrypt(password, storedHash);
}
// 否则使用MD5验证(兼容旧版本)
return VerifyPasswordMD5(account, password, storedHash);
}
/// <summary>
/// 生成新版本密码哈希(BCrypt)
/// </summary>
/// <param name="password">原始密码</param>
/// <returns>BCrypt哈希字符串</returns>
public string CreatePasswordHash(string password)
{
return HashPasswordBCrypt(password);
}
/// <summary>
/// 检查密码哈希是否为BCrypt格式(新版本)
/// </summary>
/// <param name="hashedPassword">密码哈希</param>
/// <returns>是否为BCrypt格式</returns>
public bool IsBCryptHash(string? hashedPassword)
{
if (string.IsNullOrWhiteSpace(hashedPassword))
{
return false;
}
// BCrypt哈希格式:$2a$, $2b$, $2x$, $2y$ 开头
return hashedPassword.StartsWith("$2a$")
|| hashedPassword.StartsWith("$2b$")
|| hashedPassword.StartsWith("$2x$")
|| hashedPassword.StartsWith("$2y$");
}
/// <summary>
/// 检查密码是否使用了新版本算法(BCrypt)
/// </summary>
/// <param name="hashedPassword">密码哈希</param>
/// <returns>是否为新版本密码</returns>
public bool IsNewVersionPassword(string? hashedPassword)
{
return IsBCryptHash(hashedPassword);
}
}
上述代码实现了一个密码哈希服务,主要用于处理用户密码的哈希和验证。它使用了两种密码哈希算法:BCrypt(新版本)和MD5(旧版本),以便兼容旧系统。以下是代码的主要功能和结构的详细解释:
IPasswordHashService 接口的类,负责密码的哈希和验证。HashPasswordBCrypt 方法来生成BCrypt哈希。$2a$, $2b$, $2x$, 或 $2y$ 开头。这个 PasswordHashService 类提供了一种安全的方式来处理用户密码的存储和验证。它通过支持BCrypt和MD5两种算法,确保了对旧系统的兼容性,同时也利用BCrypt的安全性来保护新用户的密码。通过智能验证方法,用户可以无缝地在新旧哈希之间进行转换。
