假设我已经实现了一种在用户面板中更改密码的方法。进行更改之前,我要求用户输入当前密码,而我实际上创建了此方法:
[HttpPost]
[ValidateAntiForgeryToken]
public bool CheckCurrentPassword(string username, string password)
{
var originalUser = _userManager.Users.FirstOrDefault(c => c.UserName == username);
var hash = _userManager.PasswordHasher.HashPassword(originalUser, password);
if (hash == originalUser.PasswordHash)
return true;
return false;
}
基本上,我将唯一的字段username
发送到此方法,并且可以检索要求更改密码的用户。我还获得了新密码的哈希值,然后将该哈希值与数据库中存储的哈希值进行比较。
问题在于哈希值不同。我不知道为什么,但是使用相同的密码,我有两个不同的哈希值(一个存储在数据库中),另一个是通过该方法动态生成的。
也许还有另一种方法可以检查当前密码是否等于输入的密码?
答案 0 :(得分:5)
这正是UserManager<TUser>.CheckPasswordAsync(TUser, String)
的用途:
if (await _userManager.CheckPasswordAsync(originalUser, password))
{
// Yes, it's the current password.
}
在进行此操作时,最好使用UserManager.FindByNameAsync(String)获取originalUser
。整个功能可能变为:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<bool> CheckCurrentPassword(string username, string password)
{
var originalUser = await _userManager.FindByNameAsync(username);
// originalUser might be null (as in your example), so check for that accordingly.
return await _userManager.CheckPasswordAsync(originalUser, password);
}
使用Async
方法要求您的调用代码使用async/await
,在上面的示例中已将其折叠。动作支持开箱即用;处理Task<T>
的返回类型。
如果您对CheckPasswordAsync
函数的实现方式感兴趣,可以在source code中亲自了解一下,这可能会帮助您确定自己的版本为何不起作用。
答案 1 :(得分:0)
如果哈希值不同,则在将密码输入数据库之前用于对密码进行哈希处理的方法必须与_userManager.PasswordHasher.HashPassword
不同。真的想不出任何其他解释。看看您是否能够匹配两种哈希方式。
答案 2 :(得分:0)
我也遇到了这个问题,这是由于在MVC项目中进行的哈希处理被SQL数据库以某种方式操纵的,所以这种方式(下面)是我设法解决具有以下问题的方法比较输入的密码和比较SQL数据库中的现有密码时,哈希密码未命中。
您可以尝试将输入的密码与现有密码进行比较的稍微不同的方式。
public ActionResult Login(UserLogin login)
{
var v = dc.Users.Where(a => a.UserEmailAddress == login.UserEmailAddress).FirstOrDefault();
if(string.Compare(Crypto.Hash(login.UserPassword), v.UserPassword) == 0)
{
//do login here
}
}
因此,如果您已将控制器设置为接受来自表单的登录详细信息,则可以使用“登录”在您尝试登录的数据库中找到该用户。在查询中,您可以继续执行“ string.Compare”
我希望这会有所帮助。