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);
}
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);
}
[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);
}
与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);
}
[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; }
}
8 回答
In current release
假设您已经处理了重置忘记密码的请求的验证,请使用以下代码作为示例代码步骤 .
In AspNet Nightly Build
更新框架以与Token一起处理ForgetPassword等请求 . 一旦发布,预计会提供简单的代码指导 .
Update:
此更新仅用于提供更明确的步骤 .
如果要使用UserManager更改密码但不想提供用户的当前密码,则可以生成密码重置令牌,然后立即使用它 .
已弃用
这是最初的答案 . 它确实有效,但有问题 . 如果
AddPassword
失败怎么办?用户没有密码 .原答案:我们可以使用三行代码:
另见:http://msdn.microsoft.com/en-us/library/dn457095(v=vs.111).aspx
现在推荐
最好使用EdwardBrey proposed和DanielWright later elaborated的答案和代码示例 .
在你的
UserManager
上,首先拨打GeneratePasswordResetTokenAsync . 一旦用户验证了他的身份(例如通过在电子邮件中接收令牌),将令牌传递给ResetPasswordAsync .这段代码取自AspNetIdentitySample项目available on github
在
UserManager<TUser, TKey>
中创建方法如果密码重置,建议通过向注册用户电子邮件发送密码重置令牌来重置密码,并要求用户提供新密码 . 如果使用默认配置设置在Identity框架上创建了一个易于使用的.NET库 . 您可以在blog link和source code找到github的详细信息 .
我认为Microsoft身份ASP.NET指南是一个良好的开端 .
https://docs.microsoft.com/en-us/aspnet/identity/overview/features-api/account-confirmation-and-password-recovery-with-aspnet-identity
Note:
如果您不使用AccountController并且不想重置密码,请使用
Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
. 如果你没有相同的OwinContext,你需要像OwinContext
那样创建一个新的DataProtectorTokenProvider
. 默认情况下,请查看App_Start -> IdentityConfig.cs
. 应该看起来像new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
.可以像这样创建:
没有Owin:
与Owin:
需要使用相同的名称创建
DpapiDataProtectionProvider
和DataProtectorTokenProvider
才能使密码重置生效 . 使用Owin创建密码重置令牌,然后使用其他名称创建新的DpapiDataProtectionProvider
将无效 .我用于ASP.NET身份的代码:
Web.Config中:
AccountController.cs: