wake-up-neo.net

Kennwort für die ASP.NET-Identitätsänderung

Ich brauche die Möglichkeit, das Passwort für den Benutzer durch den Administrator zu ändern. Daher sollte der Administrator kein aktuelles Passwort des Benutzers eingeben. Er sollte die Möglichkeit haben, ein neues Passwort festzulegen. Ich schaue mir die ChangePasswordAsync-Methode an, aber diese Methode erfordert die Eingabe eines alten Kennworts. Daher ist diese Methode für diese Aufgabe nicht geeignet. Deshalb habe ich es auf folgende Weise gemacht:

    [HttpPost]
    public async Task<ActionResult> ChangePassword(ViewModels.Admin.ChangePasswordViewModel model)
    {
        var userManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
        var result = await userManager.RemovePasswordAsync(model.UserId);
        if (result.Succeeded)
        {
            result = await userManager.AddPasswordAsync(model.UserId, model.Password);
            if (result.Succeeded)
            {
                return RedirectToAction("UserList");
            }
            else
            {
                ModelState.AddModelError("", result.Errors.FirstOrDefault());
            }
        }
        else
        {
            ModelState.AddModelError("", result.Errors.FirstOrDefault());
        }
        return View(model);
    }

es funktioniert, aber theoretisch können wir Fehler in der AddPasswordAsync-Methode erhalten. Das alte Passwort wird also entfernt, aber es wird kein neues festgelegt. Es ist nicht gut. Irgendeine Möglichkeit, es in "einer Transaktion" zu tun? PS. Ich habe die ResetPasswordAsync-Methode mit Reset-Token gesehen, scheint sicherer zu sein (da es mit dem Benutzer keine instabile Situation geben kann), aber auf jeden Fall macht es zwei Aktionen. 

37
Oleg Sh

ApplicationUserManager ist die von der ASP.NET-Vorlage generierte Klasse. 

Das heißt, Sie können es bearbeiten und alle Funktionen hinzufügen, die es noch nicht hat. Die UserManager-Klasse verfügt über eine geschützte Eigenschaft mit dem Namen Store, die einen Verweis auf die UserStore-Klasse (oder eine Unterklasse davon) speichert, je nachdem, wie Sie Ihre ASP.NET-Identität konfiguriert haben oder ob benutzerdefinierte Implementierungen für Benutzerspeicher verwendet werden, d wie 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);
    }
}

Die UserManager ist nichts anderes als ein Wrapper für die zugrunde liegende UserStore. Schauen Sie sich die IUserPasswordStore-Schnittstellendokumentation unter MSDN über verfügbare Methoden an. 

Edit: Die PasswordHasher ist auch eine öffentliche Eigenschaft der UserManager-Klasse, siehe Schnittstellendefinition hier .

Edit 2: Da einige Leute naiv glauben, dass Sie auf diese Weise keine Kennwortüberprüfung durchführen können, habe ich sie aktualisiert. Die PasswordHasher-Eigenschaft ist auch eine Eigenschaft von UserManager. Sie kann durch Hinzufügen von zwei Zeilen Code auch zur Kennwortüberprüfung hinzugefügt werden (was jedoch keine Voraussetzung für die ursprüngliche Frage war).

26
Tseng

Diese Methode hat für mich funktioniert:

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();
}
43
bryan c

BEARBEITEN: Ich weiß, dass das OP eine Antwort angefordert hat, die die Aufgabe in einer Transaktion ausführt, aber ich denke, der Code ist für Menschen nützlich.

Alle Antworten verwenden den PasswordHasher direkt, was keine gute Idee ist, da dadurch die Funktionalität (Validierung usw.) verloren geht.

Eine Alternative (und ich würde davon ausgehen, dass der empfohlene Ansatz) ist, ein Token zum Zurücksetzen des Passworts zu erstellen und dieses dann zum Ändern des Passworts zu verwenden. Beispiel:

var user = await UserManager.FindByIdAsync(id);

var token = await UserManager.GeneratePasswordResetTokenAsync(user);

var result = await UserManager.ResetPasswordAsync(user, token, "[email protected]");
33
Lee Gunn

Dies ist nur eine Verfeinerung der Antwort von @Tseng. (Ich musste es anpassen, damit es funktioniert). 

public class AppUserManager : UserManager<AppUser, int>
{
    .
    // standard methods...
    .

    public async Task<IdentityResult> ChangePasswordAsync(AppUser user, string newPassword)
    {
        if (user == null)
            throw new ArgumentNullException(nameof(user));

        var store = this.Store as IUserPasswordStore<AppUser, int>;
        if (store == null)
        {
            var errors = new string[] { "Current UserStore doesn't implement IUserPasswordStore" };
            return IdentityResult.Failed(errors);
        }

        var newPasswordHash = this.PasswordHasher.HashPassword(newPassword);
        await store.SetPasswordHashAsync(user, newPasswordHash);
        await store.UpdateAsync(user);
        return IdentityResult.Success;
    }
}

Hinweis: Dies gilt speziell für ein modifiziertes Setup, das int als Primärschlüssel für Benutzer und Rollen verwendet. Ich glaube, es wäre einfach eine Sache, die <AppUser, int>-Typen zu entfernen, damit sie mit der Standardeinstellung von ASP.NET Identity funktionieren. 

5
BCA
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; }
    }

Hinweis: Hier wird die UserId vom aktuell geloggten Benutzer abgerufen.

2
Mansur Haider

Wenn Sie nicht über das aktuelle Kennwort des Benutzers verfügen und das Kennwort dennoch ändern möchten. Was Sie stattdessen tun könnten, entfernen Sie zuerst das Benutzerpasswort und fügen Sie dann das neue Passwort hinzu. Auf diese Weise können Sie das Kennwort des Benutzers ändern, ohne das aktuelle Kennwort dieses Benutzers zu benötigen.

await UserManager.RemovePasswordAsync(user);
await UserManager.AddPasswordAsync(user, model.Password);
1
Munam Yousuf
public async Task<ActionResult> ChangePassword(ResetPasswordViewModel CP)
{
     ApplicationDbContext context = new ApplicationDbContext();
     UserStore<ApplicationUser> store = new UserStore<ApplicationUser>(context);
     UserManager<ApplicationUser> UserManager = new UserManager<ApplicationUser>(store);
     var user = await UserManager.FindAsync(User.Identity.Name, CP.CurrentPassword);

     if (!UserManager.CheckPassword(user, CP.CurrentPassword))
     {
           ViewBag.notification = "Incorrect password.";
           return View("~/Views/User/settings.cshtml");
     }
     else
     {
           if (CP.Password != CP.ConfirmPassword)
           {
                 ViewBag.notification = "try again";
                 return View("~/Views/User/settings.cshtml");
           }
           else
           {
                 String hashedNewPassword = UserManager.PasswordHasher.HashPassword(CP.Password);
                 await store.SetPasswordHashAsync(user, hashedNewPassword);
                 await store.UpdateAsync(user);
                 ViewBag.notification = "successful";
                 return View("~/Views/User/settings.cshtml");
            }
      }
 }
0
Majid joghataey