简体   繁体   中英

How to check if entered password is equal to stored password?

Suppose I've implemented a method to change the password in the user panel. Before doing the change, I ask to the user to enter the current password, I actually created this method:

[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;
}

essentially I send to this method the username which is an unique field and I can retrieve the user which asked for password change. I get also the hash of the new password and then compare the hash to the stored hash in the database.

The problem is that the hash is different. I don't know why but with the same password I have two different hashes (one stored in the db) and another generated on the fly by the method.

Maybe there is another way to check if the current password is equal to the entered password?

This is exactly what UserManager<TUser>.CheckPasswordAsync(TUser, String) is for:

if (await _userManager.CheckPasswordAsync(originalUser, password))
{
    // Yes, it's the current password.
}

While you're at it, you're better off using UserManager.FindByNameAsync(String) to get your originalUser . The entire function could become:

[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);
}

Using the Async methods requires your calling code to use async/await , which I've folded into the example above. Actions support this out of the box; handling a return type of Task<T> .

If you're interested in how the CheckPasswordAsync function is implemented, you can see for yourself in the source code , which might help you determine why your own version isn't working.

If the hashes are different then the method used to hash the password before entering it into the database must be different from _userManager.PasswordHasher.HashPassword . Can't really think of any other explanation. See if you are able to match the two ways of hashing.

I also encountered this problem, it was caused because the Hashing that was being made in the MVC project got manipulated by the SQL Database in some way, so this way (below) is how I managed to work around the issue of having a miss match in hashed password when comparing entered password and comparing to existing password in SQL Database.

You could try a slightly different way of comparing the entered password with the existing password.

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
  }
}

So if you have your controller set up to accept the login details from the form, you will be able to use the "login" to find the User in the database that you are trying to log in. With this User being found in the query, u can then proceed to perform the "string.Compare"

I hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM