我目前正在使用新的 ASP.NET 身份框架。
我必须实现一种方法来检查用户希望将其密码更改为的密码过去是否被使用过。我有一个包含已停用哈希值及其相应盐的表。
我无法弄清楚的是如何使用特定的盐生成哈希,以便我可以将新密码与停用的密码进行比较。我已经看过UserManager.PasswordHasher.HashPassword(password),但我没有看到指定盐的重载。
如何使用Identity散列密码并指定盐?
只需像当前验证密码一样验证密码即可。您需要做的就是将当前密码存储的相同信息存储在旧密码中,并检查它们都没有验证
bool UserReusedPassword(string username, string password)
{
foreach(string oldHash in GetOldHashesForUser(username)
{
if(UserManager.PasswordHasher.VerifyHashedPassword(oldHash, password) != PasswordVerificationResult.Failed)
{
return true;
}
}
return false;
}
使用 UserManager.PasswordHasher
,Salt 存储为哈希字符串的前几个字节,因此您不需要"手动输入 SALT"VerifyHashedPassword
会自动读取它并为验证过程设置它。
你不能使用特定的盐。但是,您应该为每个密码使用不同的盐。因此,您的HashPassword方法负责盐的生成。下面是一个例子(主要受Mircosoft默认实现的启发):
public string HashPassword(string password)
{
if (password == null) throw new ArgumentNullException("password");
int saltSize = 16;
int iterations = 4000;
byte[] salt;
byte[] bytes;
using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, saltSize, iterations))
{
salt = rfc2898DeriveBytes.Salt;
bytes = rfc2898DeriveBytes.GetBytes(32);
}
byte[] inArray = new byte[saltSize + 32];
Buffer.BlockCopy((Array)salt, 0, (Array)inArray, 0, saltSize);
Buffer.BlockCopy((Array)bytes, 0, (Array)inArray, saltSize, 32);
return Convert.ToBase64String(inArray);
}
如您所见,盐嵌入在 HashPassword 方法的结果中,因此当您需要验证密码时,您可以提取盐和哈希并进行验证。
可以在此处查看从 SQL 成员身份到标识的迁移示例。SQL 成员资格使用密码盐进行加密,本文概述了自定义密码哈希程序中的挂钩以重用这些密码。