How to Implement Password Resets?

前端 未结 7 1853
离开以前
离开以前 2020-12-07 07:05

I\'m working on an application in ASP.NET, and was wondering specifically how I could implement a Password Reset function if I wanted to roll my own.

S

7条回答
  •  北荒
    北荒 (楼主)
    2020-12-07 07:39

    I think Microsoft guide for ASP.NET Identity is a good start.

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

    Code that I use for ASP.NET Identity:

    Web.Config:

    
    

    AccountController.cs:

    [Route("RequestResetPasswordToken/{email}/")]
    [HttpGet]
    [AllowAnonymous]
    public async Task 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 = "" +
                   "

    Password reset

    " + $"

    Hi {user.FullName}, please click this link to reset your password

    " + ""; 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 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 = "" + "

    Your password for Client was reset

    " + $"

    Hi {user.FullName}!

    " + "

    Your password for Client was reset. Please inform us if you did not request this change.

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

提交回复
热议问题