webentwicklung-frage-antwort-db.com.de

Kennwort für das Zurücksetzen der ASP.NET-Identität

Wie kann ich das Kennwort eines Benutzers im neuen ASP.NET-Identitätssystem erhalten? Oder wie kann ich zurücksetzen, ohne das aktuelle zu kennen (Benutzer hat Passwort vergessen)?

81
daniel

In der aktuellen Version

Angenommen, Sie haben die Überprüfung der Anforderung zum Zurücksetzen des vergessenen Kennworts ausgeführt, verwenden Sie den folgenden Code als Beispielcode.

ApplicationDbContext =new ApplicationDbContext()
String userId = "<YourLogicAssignsRequestedUserId>";
String newPassword = "<PasswordAsTypedByUser>";
ApplicationUser cUser = UserManager.FindById(userId);
String hashedNewPassword = UserManager.PasswordHasher.HashPassword(newPassword);
UserStore<ApplicationUser> store = new UserStore<ApplicationUser>();            
store.SetPasswordHashAsync(cUser, hashedNewPassword);

In AspNet Nightly Build

Das Framework wird aktualisiert, um mit Token zusammenzuarbeiten, um Anforderungen wie ForgetPassword zu behandeln. Einmal in der Veröffentlichung wird eine einfache Code-Anleitung erwartet.

Update:

Dieses Update soll lediglich klarere Schritte ermöglichen.

ApplicationDbContext context = new ApplicationDbContext();
UserStore<ApplicationUser> store = new UserStore<ApplicationUser>(context);
UserManager<ApplicationUser> UserManager = new UserManager<ApplicationUser>(store);
String userId = User.Identity.GetUserId();//"<YourLogicAssignsRequestedUserId>";
String newPassword = "[email protected]"; //"<PasswordAsTypedByUser>";
String hashedNewPassword = UserManager.PasswordHasher.HashPassword(newPassword);                    
ApplicationUser cUser = await store.FindByIdAsync(userId);
await store.SetPasswordHashAsync(cUser, hashedNewPassword);
await store.UpdateAsync(cUser);
92
jd4u

Oder wie kann ich zurücksetzen, ohne das aktuelle zu kennen (Benutzer hat Passwort vergessen)?

Wenn Sie ein Kennwort mit dem UserManager ändern möchten, das aktuelle Kennwort des Benutzers jedoch nicht angeben möchten, können Sie ein Kennwort-Reset-Token generieren und es sofort verwenden.

string resetToken = await UserManager.GeneratePasswordResetTokenAsync(model.Id);
IdentityResult passwordChangeResult = await UserManager.ResetPasswordAsync(model.Id, resetToken, model.NewPassword);
113
Daniel Wright

Veraltet

Dies war die ursprüngliche Antwort. Es funktioniert, hat aber ein Problem. Was passiert, wenn AddPassword fehlschlägt? Der Benutzer hat kein Passwort.

Die ursprüngliche Antwort: Wir können drei Codezeilen verwenden:

UserManager<IdentityUser> userManager = 
    new UserManager<IdentityUser>(new UserStore<IdentityUser>());

userManager.RemovePassword(userId);

userManager.AddPassword(userId, newPassword);

Siehe auch: http://msdn.Microsoft.com/de-de/library/dn457095(v=vs.111).aspx

Jetzt empfohlen

Es ist wahrscheinlich besser, die Antwort zu verwenden, die EdwardBrey vorgeschlagen hat und dann DanielWright später erarbeitete mit einem Codebeispiel.

68
Shaun Luttin

Rufen Sie in Ihrer UserManager zuerst GeneratePasswordResetTokenAsync auf. Wenn der Benutzer seine Identität bestätigt hat (z. B. durch Empfangen des Tokens in einer E-Mail), übergeben Sie das Token an ResetPasswordAsync .

27
Edward Brey

Methode in UserManager<TUser, TKey> erstellen

public Task<IdentityResult> ChangePassword(int userId, string newPassword)
{
     var user = Users.FirstOrDefault(u => u.Id == userId);
     if (user == null)
          return new Task<IdentityResult>(() => IdentityResult.Failed());

     var store = Store as IUserPasswordStore<User, int>;
     return base.UpdatePassword(store, user, newPassword);
}
2
tmg
string message = null;
//reset the password
var result = await IdentityManager.Passwords.ResetPasswordAsync(model.Token, model.Password);
if (result.Success)
{
    message = "The password has been reset.";
    return RedirectToAction("PasswordResetCompleted", new { message = message });
}
else
{
    AddErrors(result);
}

Dieses Codefragment wird aus dem AspNetIdentitySample-Projekt entnommen verfügbar auf github

2
sclarson

Bei einem Zurücksetzen des Passworts wird empfohlen, das Passwort zurückzusetzen, indem Sie das Passwort-Reset-Token an die E-Mail des registrierten Benutzers senden und den Benutzer zur Eingabe eines neuen Passworts auffordern. Wenn Sie eine leicht zu verwendende .NET-Bibliothek über Identity Framework mit Standardkonfigurationseinstellungen erstellt haben. Details finden Sie unter blog link und source code bei github.

1
Rahul Garg

Ich denke, Microsoft-Leitfaden für ASP.NET Identity ist ein guter Anfang.

https://docs.Microsoft.com/en-us/aspnet/identity/overview/features-api/account-confirmation-and-password-recovery-with-aspnet-identity

Hinweis:

Wenn Sie AccountController nicht verwenden und Ihr Kennwort nicht zurücksetzen möchten, verwenden Sie Request.GetOwinContext().GetUserManager<ApplicationUserManager>();. Wenn Sie nicht über denselben OwinContext verfügen, müssen Sie eine neue DataProtectorTokenProvider erstellen, wie sie von OwinContext verwendet wird. Schauen Sie sich standardmäßig App_Start -> IdentityConfig.cs an. Sollte so aussehen wie new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));.

Könnte so erstellt werden:

Ohne Owin:

[HttpGet]
[AllowAnonymous]
[Route("testReset")]
public IHttpActionResult TestReset()
{
    var db = new ApplicationDbContext();
    var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(db));
    var provider = new DpapiDataProtectionProvider("SampleAppName");
    manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(
        provider.Create("SampleTokenName"));

    var email = "[email protected]";

    var user = new ApplicationUser() { UserName = email, Email = email };

    var identityUser = manager.FindByEmail(email);

    if (identityUser == null)
    {
        manager.Create(user);
        identityUser = manager.FindByEmail(email);
    }

    var token = manager.GeneratePasswordResetToken(identityUser.Id);
    return Ok(HttpUtility.UrlEncode(token));
}

[HttpGet]
[AllowAnonymous]
[Route("testReset")]
public IHttpActionResult TestReset(string token)
{
    var db = new ApplicationDbContext();
    var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(db));
    var provider = new DpapiDataProtectionProvider("SampleAppName");
    manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(
        provider.Create("SampleTokenName"));
    var email = "[email protected]";
    var identityUser = manager.FindByEmail(email);
    var valid = Task.Run(() => manager.UserTokenProvider.ValidateAsync("ResetPassword", token, manager, identityUser)).Result;
    var result = manager.ResetPassword(identityUser.Id, token, "TestingTest1!");
    return Ok(result);
}

Mit Owin:

[HttpGet]
[AllowAnonymous]
[Route("testResetWithOwin")]
public IHttpActionResult TestResetWithOwin()
{
    var manager = Request.GetOwinContext().GetUserManager<ApplicationUserManager>();

    var email = "[email protected]";

    var user = new ApplicationUser() { UserName = email, Email = email };

    var identityUser = manager.FindByEmail(email);

    if (identityUser == null)
    {
        manager.Create(user);
        identityUser = manager.FindByEmail(email);
    }

    var token = manager.GeneratePasswordResetToken(identityUser.Id);
    return Ok(HttpUtility.UrlEncode(token));
}

[HttpGet]
[AllowAnonymous]
[Route("testResetWithOwin")]
public IHttpActionResult TestResetWithOwin(string token)
{
    var manager = Request.GetOwinContext().GetUserManager<ApplicationUserManager>();

    var email = "[email protected]";
    var identityUser = manager.FindByEmail(email);
    var valid = Task.Run(() => manager.UserTokenProvider.ValidateAsync("ResetPassword", token, manager, identityUser)).Result;
    var result = manager.ResetPassword(identityUser.Id, token, "TestingTest1!");
    return Ok(result);
}

Die Variablen DpapiDataProtectionProvider und DataProtectorTokenProvider müssen mit demselben Namen erstellt werden, damit das Kennwort zurückgesetzt werden kann. Die Verwendung von Owin zum Erstellen des Kennwort-Reset-Tokens und das Erstellen einer neuen DpapiDataProtectionProvider mit einem anderen Namen funktionieren nicht. 

Code, den ich für ASP.NET-Identität verwende:

Web.Config:

<add key="AllowedHosts" value="example.com,example2.com" />

AccountController.cs:

[Route("RequestResetPasswordToken/{email}/")]
[HttpGet]
[AllowAnonymous]
public async Task<IHttpActionResult> GetResetPasswordToken([FromUri]string email)
{
    if (!ModelState.IsValid)
        return BadRequest(ModelState);

    var user = await UserManager.FindByEmailAsync(email);
    if (user == null)
    {
        Logger.Warn("Password reset token requested for non existing email");
        // Don't reveal that the user does not exist
        return NoContent();
    }

    //Prevent Host Header Attack -> Password Reset Poisoning. 
    //If the IIS has a binding to accept connections on 80/443 the Host parameter can be changed.
    //See https://security.stackexchange.com/a/170759/67046
    if (!ConfigurationManager.AppSettings["AllowedHosts"].Split(',').Contains(Request.RequestUri.Host)) {
            Logger.Warn($"Non allowed Host detected for password reset {Request.RequestUri.Scheme}://{Request.Headers.Host}");
            return BadRequest();
    }

    Logger.Info("Creating password reset token for user id {0}", user.Id);

    var Host = $"{Request.RequestUri.Scheme}://{Request.Headers.Host}";
    var token = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
    var callbackUrl = $"{Host}/resetPassword/{HttpContext.Current.Server.UrlEncode(user.Email)}/{HttpContext.Current.Server.UrlEncode(token)}";

    var subject = "Client - Password reset.";
    var body = "<html><body>" +
               "<h2>Password reset</h2>" +
               $"<p>Hi {user.FullName}, <a href=\"{callbackUrl}\"> please click this link to reset your password </a></p>" +
               "</body></html>";

    var message = new IdentityMessage
    {
        Body = body,
        Destination = user.Email,
        Subject = subject
    };

    await UserManager.EmailService.SendAsync(message);

    return NoContent();
}

[HttpPost]
[Route("ResetPassword/")]
[AllowAnonymous]
public async Task<IHttpActionResult> ResetPasswordAsync(ResetPasswordRequestModel model)
{
    if (!ModelState.IsValid)
        return NoContent();

    var user = await UserManager.FindByEmailAsync(model.Email);
    if (user == null)
    {
        Logger.Warn("Reset password request for non existing email");
        return NoContent();
    }            

    if (!await UserManager.UserTokenProvider.ValidateAsync("ResetPassword", model.Token, UserManager, user))
    {
        Logger.Warn("Reset password requested with wrong token");
        return NoContent();
    }

    var result = await UserManager.ResetPasswordAsync(user.Id, model.Token, model.NewPassword);

    if (result.Succeeded)
    {
        Logger.Info("Creating password reset token for user id {0}", user.Id);

        const string subject = "Client - Password reset success.";
        var body = "<html><body>" +
                   "<h1>Your password for Client was reset</h1>" +
                   $"<p>Hi {user.FullName}!</p>" +
                   "<p>Your password for Client was reset. Please inform us if you did not request this change.</p>" +
                   "</body></html>";

        var message = new IdentityMessage
        {
            Body = body,
            Destination = user.Email,
            Subject = subject
        };

        await UserManager.EmailService.SendAsync(message);
    }

    return NoContent();
}

public class ResetPasswordRequestModel
{
    [Required]
    [Display(Name = "Token")]
    public string Token { get; set; }

    [Required]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 10)]
    [DataType(DataType.Password)]
    [Display(Name = "New password")]
    public string NewPassword { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm new password")]
    [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}
0
Ogglas