首页 文章

ASP.NET身份重置密码

提问于
浏览
85

如何在新的ASP.NET身份系统中获取用户的密码?或者如何在不知道当前密码(用户忘记密码)的情况下重置?

8 回答

  • 68

    In current release

    假设您已经处理了重置忘记密码的请求的验证,请使用以下代码作为示例代码步骤 .

    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

    更新框架以与Token一起处理ForgetPassword等请求 . 一旦发布,预计会提供简单的代码指导 .

    Update:

    此更新仅用于提供更明确的步骤 .

    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);
    
  • 2

    或者如何在不知道当前密码的情况下重置(用户忘记密码)?

    如果要使用UserManager更改密码但不想提供用户的当前密码,则可以生成密码重置令牌,然后立即使用它 .

    string resetToken = await UserManager.GeneratePasswordResetTokenAsync(model.Id);
    IdentityResult passwordChangeResult = await UserManager.ResetPasswordAsync(model.Id, resetToken, model.NewPassword);
    
  • 27

    已弃用

    这是最初的答案 . 它确实有效,但有问题 . 如果 AddPassword 失败怎么办?用户没有密码 .

    原答案:我们可以使用三行代码:

    UserManager<IdentityUser> userManager = 
        new UserManager<IdentityUser>(new UserStore<IdentityUser>());
    
    userManager.RemovePassword(userId);
    
    userManager.AddPassword(userId, newPassword);
    

    另见:http://msdn.microsoft.com/en-us/library/dn457095(v=vs.111).aspx

    现在推荐

    最好使用EdwardBrey proposedDanielWright later elaborated的答案和代码示例 .

  • 93

    在你的 UserManager 上,首先拨打GeneratePasswordResetTokenAsync . 一旦用户验证了他的身份(例如通过在电子邮件中接收令牌),将令牌传递给ResetPasswordAsync .

  • 1
    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);
    }
    

    这段代码取自AspNetIdentitySample项目available on github

  • 2

    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);
    }
    
  • 0

    如果密码重置,建议通过向注册用户电子邮件发送密码重置令牌来重置密码,并要求用户提供新密码 . 如果使用默认配置设置在Identity框架上创建了一个易于使用的.NET库 . 您可以在blog linksource code找到github的详细信息 .

  • 114

    我认为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:

    [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);
    }
    

    需要使用相同的名称创建 DpapiDataProtectionProviderDataProtectorTokenProvider 才能使密码重置生效 . 使用Owin创建密码重置令牌,然后使用其他名称创建新的 DpapiDataProtectionProvider 将无效 .

    我用于ASP.NET身份的代码:

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

相关问题