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

29
Microsoft正在推出一个名为ASP.NET Identity的新会员系统(也是ASP.NET MVC 5的默认系统)。我找到了示例项目,但它没有实现密码重置。
在密码重置方面,我只发现了这篇文章:使用One ASP.NET Identity实现用户确认和密码重置-痛苦还是快乐,对我没有帮助,因为它不使用内置的密码恢复功能。
当我看到选项时,我认为我们需要生成一个重置令牌,然后将其发送给用户。用户可以使用令牌设置新密码,覆盖旧密码。
我找到了 IdentityManager.Passwords.GenerateResetPasswordToken / IdentityManager.Passwords.GenerateResetPasswordTokenAsync(string tokenId, string userName, validUntilUtc),但是我不知道 tokenId 参数的含义。
如何在ASP.NET MVC 5.0中实现密码重置?

1
感谢您的帮助和支持!我的问题是,描述的方法(IdentityManager.Passwords.GenerateResetPasswordToken)无法在任何地方找到任何信息,因此我无法使用它。但无论如何,我很快就会弥补缺少的信息,并包含有效的代码! - Gábor Plesz
那么 IdentityManagerUserManager 有何区别?当我创建了一个新项目时,AccountController 使用了 UserManager - Eonasdan
1
我已将您的答案移动到您的回答中,而不是在问题中。 - George Stocker
2
请查看我的教程:使用ASP.NET Identity进行帐户确认和密码恢复 http://www.asp.net/identity/overview/features-api/account-confirmation-and-password-recovery-with-aspnet-identity - RickAndMSFT
链接已失效,请重新获取。 - Cerveser
2个回答

9
我明白了:tokenid是一个自由选择的身份标识符,用于识别密码选项。例如,
1. 看起来像是密码恢复过程的第一步 (它基于:https://dev59.com/WXRB5IYBdhLWcg3wUFrB#698879
[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
                   )
           );
}

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

这是一个骨架提案,用于在 GitHub 上建立 示例项目 ,如果有人需要可以测试。邮件发送功能尚未编写,可能会很快添加。


IdentityManager是什么,它来自哪里? - Stuart Dobson
1
我也想知道什么是“IdentityManager”。请帮忙。 - Jedaias Rodrigues
@stuartdotnet ASP.NET Identity系统旨在取代以前的ASP.NET Membership和Simple Membership系统。 http://www.asp.net/identity - Gábor Plesz
我也无法使用 IdentityManager,也无法找到 GenerateResetPasswordTokenAsync 方法从哪里来。 - Machado

5

看起来很麻烦... 那么与以下方法相比,有什么优势呢:

  1. 用户点击“恢复账户”链接
  2. 这会向电子邮件发送一个64字节编码的日期时间刻度值的字符串(称其为伪哈希)
  3. 点击电子邮件中的链接,返回到控制器/动作路由
  4. 匹配电子邮件及其源服务器到伪哈希,解密伪哈希,验证自发送以来的时间,并
  5. 提供一个视图供用户设置新密码
  6. 使用有效密码后,代码会删除旧用户密码并分配新密码。
  7. 完成后,无论成功与否,都要删除伪哈希。

通过这种流程,您永远不会将密码发送出域。

请有人证明一下这种方法如何不安全。


10
我本来想删除这个答案,但还是保留下来以便观察它的错误思维过程。1. Asp.Net密码重置流程经过了标准化和验证。2. 没有密码通过网络发送。3. 为什么要重复发明轮子呢?4. 一旦你了解了Identity 2.1+中密码恢复的工作原理,你会发现它非常简单,为什么要费力地开发其他东西——包括设计和充分测试你的进程以通过安全审核所需的时间。不要像我的回答建议的那样做——它只是浪费时间。 - Robert Achmann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接