关于c#:如何使用ASP.NET Identity for ASP.NET MVC 5.0实现密码重置?

How do I implement password reset with ASP.NET Identity for ASP.NET MVC 5.0?

微软正在开发一种称为ASP.NET标识的新成员系统(也是ASP.NET MVC 5中的默认成员)。我找到了示例项目,但这并没有实现密码重置。

关于密码重置主题,刚刚找到了这篇文章:用一个ASP.NET标识实现用户确认和密码重置-痛苦或快乐,对我没有帮助,因为不使用内置的密码恢复。

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

我找到了IdentityManager.Passwords.GenerateResetPasswordToken/IdentityManager.Passwords.GenerateResetPasswordTokenAsync(string tokenId, string userName, validUntilUtc),但我不知道这可能意味着什么tokenId参数。

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


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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
[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,然后当用户输入令牌和新密码时:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[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上的示例项目的框架建议,如果有人需要,可以对其进行测试。发送的电子邮件尚未编写,可能很快就会添加。


好像有很多麻烦…以上所述的优势有哪些:

  • 用户单击"恢复帐户"链接
  • 这将在电子邮件中发送一个由日期时间刻度值(称为psuedo散列)组成的64字节编码字符串。
  • 单击电子邮件中指向控制器/操作路由的链接
  • 匹配电子邮件及其源服务器到psuedo哈希,解密psuedo哈希,验证自发送以来的时间和
  • 提供用户设置新密码的视图
  • 使用有效的密码,代码将删除旧的用户密码并分配新密码。
  • 完成、成功或不成功后,删除psuedo哈希。
  • 有了这个流程,您就永远不会从您的域中发送密码。

    任何人,请向我证明这是多么的不安全。