ASP.NET Identity change password

前端 未结 10 1866
礼貌的吻别
礼貌的吻别 2020-11-29 18:09

I need ability to change password for user by admin. So, admin should not enter a current password of user, he should have ability to set a new password. I look at ChangePas

相关标签:
10条回答
  • 2020-11-29 18:27

    ApplicationUserManager is the class generated by the ASP.NET Template.

    Which means, you can edit it and add any functionality it doesn't have yet. The UserManager class has a protected property named Store which stores a reference to the UserStore class (or any subclass of it, depending on how you configured your ASP.NET Identity or if you use custom user store implementations, i.e. if you use different database engine like MySQL).

    public class AplicationUserManager : UserManager<....> 
    {
        public async Task<IdentityResult> ChangePasswordAsync(TKey userId, string newPassword) 
        {
            var store = this.Store as IUserPasswordStore;
            if(store==null) 
            {
                var errors = new string[] 
                { 
                    "Current UserStore doesn't implement IUserPasswordStore"
                };
    
                return Task.FromResult<IdentityResult>(new IdentityResult(errors) { Succeeded = false });
            }
    
            if(PasswordValidator != null)
            {
                var passwordResult = await PasswordValidator.ValidateAsync(password);
                if(!password.Result.Success)
                    return passwordResult;
            }
    
            var newPasswordHash = this.PasswordHasher.HashPassword(newPassword);
    
            await store.SetPasswordHashAsync(userId, newPasswordHash);
            return Task.FromResult<IdentityResult>(IdentityResult.Success);
        }
    }
    

    The UserManager is nothing else than a wrapper to the underlying UserStore. Check out IUserPasswordStore interface documentation at MSDN on available Methods.

    Edit: The PasswordHasher is also a public property of the UserManager class, see interface definition here.

    Edit 2: Since some people naively believe, you can't do password validation this way, I've updated it. The PasswordValidator property is also a property of UserManager and its as simple as adding 2 lines of code to add password validation too (which wasn't an requirement of the original question though).

    0 讨论(0)
  • 2020-11-29 18:32
    public async Task<IActionResult> ChangePassword(ChangePwdViewModel usermodel)
            {           
                var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
                var user = await _userManager.FindByIdAsync(userId);            
                var result = await _userManager.ChangePasswordAsync(user, usermodel.oldPassword, usermodel.newPassword);
                if (!result.Succeeded)
                {
                    //throw exception......
                }
                return Ok();
            }
    
    public class ChangePwdViewModel
        {  
            [DataType(DataType.Password), Required(ErrorMessage ="Old Password Required")]
            public string oldPassword { get; set; }
    
            [DataType(DataType.Password), Required(ErrorMessage ="New Password Required")]
            public string newPassword { get; set; }
        }
    

    Note : here UserId i am retrieving from Current logged User.

    0 讨论(0)
  • 2020-11-29 18:36
    public async Task<ActionResult> ResetUserPassword(string id, string Password)
    {
        //     Find User
        var user = await context.Users.Where(x => x.Id == id).SingleOrDefaultAsync();
        if (user == null)
        {
            return RedirectToAction("UserList");
        }
        await UserManager.RemovePasswordAsync(id);
        //     Add a user password only if one does not already exist
        await UserManager.AddPasswordAsync(id, Password);
        return RedirectToAction("UserDetail", new { id = id });
    }
    
    0 讨论(0)
  • 2020-11-29 18:39

    EDIT: I know the OP requested an answer which performs the task in one transaction but I think the code is useful to people.

    All the answers use the PasswordHasher directly which isn't a good idea as you will lose some baked in functionality (validation etc).

    An alternative (and I would assume the recommended approach) is to create a password reset token and then use that to change the password. Example:

    var user = await UserManager.FindByIdAsync(id);
    
    var token = await UserManager.GeneratePasswordResetTokenAsync(user);
    
    var result = await UserManager.ResetPasswordAsync(user, token, "MyN3wP@ssw0rd");
    
    0 讨论(0)
  • 2020-11-29 18:45

    This method worked for me:

    public async Task<IHttpActionResult> changePassword(UsercredentialsModel usermodel)
    {
      ApplicationUser user = await AppUserManager.FindByIdAsync(usermodel.Id);
      if (user == null)
      {
        return NotFound();
      }
      user.PasswordHash = AppUserManager.PasswordHasher.HashPassword(usermodel.Password);
      var result = await AppUserManager.UpdateAsync(user);
      if (!result.Succeeded)
      {
        //throw exception......
      }
      return Ok();
    }
    
    0 讨论(0)
  • 2020-11-29 18:45

    For ASP.NET Core 3.1 users, this is a modernized iteration of the excellent answers provided by @Tseng and @BCA.

    PasswordValidator is no longer a property on UserManager - instead, the property is an IList PasswordValidators. Furthermore, Identity now has a protected UpdatePasswordHash method that changes the password for you without needing to directly access the UserStore, which eliminates the need to manually hash and save the password anyway.

    UserManager also has a public property, bool SupportsUserPassword, which replaces the need to test if Store implements IUserPasswordStore (internally, this is exactly what UserManager does in the SupportsUserPassword getter).

    Since UpdatePasswordHash is protected, you do still need to extend the base UserManager. Its signature is:

    protected Task<IdentityResult> UpdatePasswordHash(TUser user, string newPassword, bool validatePassword)

    where validatePassword represents whether or not to run password validation. This does not default to true, unfortunately, so it needs to be supplied. The implementation looks like this:

    public async Task<IdentityResult> ChangePasswordAsync(ApplicationUser user, string newPassword)
    {
        if (!SupportsUserPassword)
        {
            return IdentityResult.Failed(new IdentityError
            {
                Description = "Current UserStore doesn't implement IUserPasswordStore"
            });
        }
                
        var result = await UpdatePasswordHash(user, newPassword, true);
        if (result.Succeeded)
            await UpdateAsync(user);
    
        return result;
    }
    

    As before, the first order of business is to ensure the current UserStore supports passwords.

    Then, simply call UpdatePasswordHash with the ApplicationUser, the new password, and true to update that user's password with validation. If the update was successful, you still have to save the user so call UpdateAsync.

    0 讨论(0)
提交回复
热议问题