Antworten:
In der aktuellen Version
Angenommen, Sie haben die Überprüfung der Anforderung zum Zurücksetzen des vergessenen Kennworts durchgefü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 wurde aktualisiert, um mit Token für die Bearbeitung von Anforderungen wie ForgetPassword zusammenzuarbeiten. Nach der Veröffentlichung wird eine einfache Code-Anleitung erwartet.
Aktualisieren:
Dieses Update dient nur dazu, klarere Schritte bereitzustellen.
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 = "test@123"; //"<PasswordAsTypedByUser>";
String hashedNewPassword = UserManager.PasswordHasher.HashPassword(newPassword);
ApplicationUser cUser = await store.FindByIdAsync(userId);
await store.SetPasswordHashAsync(cUser, hashedNewPassword);
await store.UpdateAsync(cUser);
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, aber nicht das aktuelle Kennwort des Benutzers angeben möchten, können Sie ein Token zum Zurücksetzen des Kennworts generieren und es stattdessen sofort verwenden.
string resetToken = await UserManager.GeneratePasswordResetTokenAsync(model.Id);
IdentityResult passwordChangeResult = await UserManager.ResetPasswordAsync(model.Id, resetToken, model.NewPassword);
SecurityStamp
für Ihren Benutzer nicht null ist. Dies kann bei Benutzern auftreten, die aus anderen Datenbanken migriert wurden, oder bei Benutzern, die nicht mithilfe einer UserManager.CreateAsync()
Methode erstellt wurden.
Dies war die ursprüngliche Antwort. Es funktioniert, hat aber ein Problem. Was ist, wenn es 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/en-us/library/dn457095(v=vs.111).aspx
Es ist wahrscheinlich besser, die Antwort zu verwenden, die EdwardBrey vorgeschlagen und DanielWright später mit einem Codebeispiel ausgearbeitet hat .
UserManager
Rufen Sie bei Ihrem ersten Aufruf GeneratePasswordResetTokenAsync auf . Wenn der Benutzer seine Identität überprüft hat (z. B. durch Empfangen des Tokens in einer E-Mail), übergeben Sie das Token an ResetPasswordAsync .
ResetPasswordAsync
einer Benutzer-ID besteht darin, dass der Identitätsanbieter nur Benutzer-IDs indizieren muss, nicht auch Token. Dadurch kann es besser skaliert werden, wenn viele Benutzer vorhanden sind.
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);
}
Dieser Codeausschnitt stammt aus dem auf github verfügbaren AspNetIdentitySample-Projekt
Methode erstellen in UserManager<TUser, TKey>
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);
}
Im Falle eines Zurücksetzens des Passworts wird empfohlen, es durch Senden eines Token zum Zurücksetzen des Passworts an die E-Mail-Adresse eines registrierten Benutzers zurückzusetzen und den Benutzer aufzufordern, ein neues Passwort anzugeben. Wenn Sie eine einfach zu verwendende .NET-Bibliothek über das Identity Framework mit Standardkonfigurationseinstellungen erstellt haben. Details finden Sie unter Blog-Link und Quellcode bei github.
Ich denke, Microsoft-Handbuch für ASP.NET Identity ist ein guter Anfang.
Hinweis:
Wenn Sie AccountController nicht verwenden und Ihr Kennwort nicht zurücksetzen möchten, verwenden Sie Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
. Wenn Sie nicht denselben OwinContext haben, müssen Sie einen neuen erstellen, DataProtectorTokenProvider
wie er OwinContext
verwendet wird. Standardmäßig anschauen App_Start -> IdentityConfig.cs
. Sollte ungefähr so aussehen 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 = "test@test.com";
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 = "test@test.com";
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 = "test@test.com";
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 = "test@test.com";
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);
}
Das DpapiDataProtectionProvider
und DataProtectorTokenProvider
muss mit demselben Namen erstellt werden, damit ein Zurücksetzen des Kennworts funktioniert. Die Verwendung von Owin zum Erstellen des Token zum Zurücksetzen des Kennworts und zum Erstellen eines neuen Tokens DpapiDataProtectionProvider
mit einem anderen Namen funktioniert nicht.
Code, den ich für die 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; }
}
Ich habe ein wenig nachgeforscht und die Lösung, die für mich funktioniert, war eine Mischung aus einigen Lösungen, die in diesem Beitrag gegründet wurden.
Ich kompiliere diese Lösung im Grunde und poste, was für mich funktioniert. In meinem Fall möchte ich kein Token aus dem .net-Kern verwenden.
public async Task ResetPassword(string userId, string password)
{
var user = await _userManager.FindByIdAsync(userId);
var hashPassword= _userManager.PasswordHasher.HashPassword(user, password);
user.PasswordHash = passwordHash;
await _userManager.UpdateAsync(user);
}
Beste Methode zum Zurücksetzen des Kennworts in Asp.Net Core Identity für die Web-API.
Hinweis * : Fehler () und Ergebnis () werden für den internen Gebrauch erstellt. Sie können zurückkehren, was Sie wollen.
[HttpPost]
[Route("reset-password")]
public async Task<IActionResult> ResetPassword(ResetPasswordModel model)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
try
{
if (model is null)
return Error("No data found!");
var user = await _userManager.FindByIdAsync(AppCommon.ToString(GetUserId()));
if (user == null)
return Error("No user found!");
Microsoft.AspNetCore.Identity.SignInResult checkOldPassword =
await _signInManager.PasswordSignInAsync(user.UserName, model.OldPassword, false, false);
if (!checkOldPassword.Succeeded)
return Error("Old password does not matched.");
string resetToken = await _userManager.GeneratePasswordResetTokenAsync(user);
if (string.IsNullOrEmpty(resetToken))
return Error("Error while generating reset token.");
var result = await _userManager.ResetPasswordAsync(user, resetToken, model.Password);
if (result.Succeeded)
return Result();
else
return Error();
}
catch (Exception ex)
{
return Error(ex);
}
}