如何使用ASP.NET Identity for ASP.NET MVC 5.0实现密码重置?

Gáb*_*esz 28 .net c# asp.net-mvc identity password-recovery

微软正在推出一个名为ASP.NET Identity新会员系统(也是ASP.NET MVC 5中的默认系统).我找到了示例项目,但是没有实现密码重置.

在密码重置主题上找到了这篇文章:使用一个ASP.NET身份实现用户确认和密码重置 - 痛苦或愉快,对我没有帮助,因为不使用内置密码恢复.

当我查看选项时,我认为我们需要生成一个重置令牌,我将发送给用户.用户可以使用令牌设置新密码,覆盖旧密码.

我找到了IdentityManager.Passwords.GenerateResetPasswordToken/ IdentityManager.Passwords.GenerateResetPasswordTokenAsync(string tokenId, string userName, validUntilUtc),但我无法弄清楚它可能意味着什么tokenId参数.

如何使用MVC 5.0在ASP.NET中实现密码重置?

Gáb*_*esz 8

我明白了:tokenid是一个自由选择的身份,它标识了一个密码选项.例如,

1.看起来像密码恢复过程,第1步 (它基于:https://stackoverflow.com/a/698879/208922)

[HttpPost]
[ValidateAntiForgeryToken]
[AllowAnonymous]
//[RecaptchaControlMvc.CaptchaValidator]
public virtual async Task<ActionResult> ResetPassword(
                                              ResetPasswordViewModel rpvm)
{
    string message = null;
    //the token is valid for one day
    var until = DateTime.Now.AddDays(1);
    //We find the user, as the token can not generate the e-mail address, 
    //but the name should be.
    var db = new Context();
    var user = db.Users.SingleOrDefault(x=>x.Email == rpvm.Email);

    var token = new StringBuilder();

    //Prepare a 10-character random text
    using (RNGCryptoServiceProvider 
                        rngCsp = new RNGCryptoServiceProvider())
    {
        var data = new byte[4];
        for (int i = 0; i < 10; i++)
        {
            //filled with an array of random numbers
            rngCsp.GetBytes(data);
            //this is converted into a character from A to Z
            var randomchar = Convert.ToChar(
                                      //produce a random number 
                                      //between 0 and 25
                                      BitConverter.ToUInt32(data, 0) % 26 
                                      //Convert.ToInt32('A')==65
                                      + 65
                             );
            token.Append(randomchar);
        }
    }
    //This will be the password change identifier 
    //that the user will be sent out
    var tokenid = token.ToString();

    if (null!=user)
    {
        //Generating a token
        var result = await IdentityManager
                                .Passwords
                                .GenerateResetPasswordTokenAsync(
                                              tokenid, 
                                              user.UserName, 
                                              until
                           );

        if (result.Success)
        {
            //send the email
            ...
        }
    }
    message = 
        "We have sent a password reset request if the email is verified.";
    return RedirectToAction(
                   MVC.Account.ResetPasswordWithToken(
                               token: string.Empty, 
                               message: message
                   )
           );
}
Run Code Online (Sandbox Code Playgroud)

2然后当用户输入令牌和新密码时:

[HttpPost]
[ValidateAntiForgeryToken]
[AllowAnonymous]
//[RecaptchaControlMvc.CaptchaValidator]
public virtual async Task<ActionResult> ResetPasswordWithToken(
                                            ResetPasswordWithTokenViewModel 
                                                        rpwtvm
                                        )
{
    if (ModelState.IsValid)
    {
        string message = null;
        //reset the password
        var result = await IdentityManager.Passwords.ResetPasswordAsync(
                                                   rpwtvm.Token, 
                                                   rpwtvm.Password
                           );
        if (result.Success)
        { 
            message = "the password has been reset.";
            return RedirectToAction(
                        MVC.Account.ResetPasswordCompleted(message: message)
                   );
        }
        else
        {
            AddErrors(result);
        }
    }
    return View(MVC.Account.ResetPasswordWithToken(rpwtvm));
}
Run Code Online (Sandbox Code Playgroud)

在github上对项目进行示例的骷髅提议,如果有人需要它可能会被测试.电子邮件发送尚未写入,可能很快就会添加.


Rob*_*ann 5

好像很麻烦......上面给出了什么好处:

  1. 用户点击"恢复帐户"链接
  2. 这会在电子邮件中发送64字节编码的日期时间刻度值(称为psuedo-hash)
  3. 单击电子邮件中的链接返回到控制器/操作路径
  4. 匹配电子邮件和它的源服务器psuedo-hash,解密psuedo-hash,验证自发送后的时间和
  5. 为用户提供了一个用于设置新密码的视图
  6. 使用有效密码,代码将删除旧用户密码并分配新密码.
  7. 一旦完成,成功与否,删除psuedo-hash.

有了这个流程,您在任何时候都不会从您的域名中发送密码.

请任何人向我证明这是不安全的.

  • 我实际上想要删除这个答案,但是把它留给了它的思考过程中的愚蠢.1. Asp.Net密码重置过程已经过标准化和验证.2.没有通过线路发送密码.3.为什么重新发明轮子?4.一旦你理解了Identity 2.1+中密码恢复的工作原理,它就是如此简单,你为什么要开发其他任何东西 - 包括设计和测试你的过程所需的时间足以通过安全集合.不要做我的答案所暗示的 - 这只是浪费时间 (10认同)