MVC4接收密码重置令牌的模式

本文关键字:令牌 模式 密码 MVC4 | 更新日期: 2023-09-27 18:27:15

正在尝试设置密码重置功能。这将适用于尚未也无法登录到系统的用户。我想我已经接近了,但感觉不对:

我有一个ResetPassword方法/视图。。。它只是询问用户的电子邮件地址,不向用户确认帐户,但如果存在帐户,则使用link+令牌发送电子邮件。这一切都很好。

下一部分是我的问题所在。。。。我用这种方法(通过点击用户的电子邮件链接)收到密码令牌:

[HttpGet]
    public ActionResult ReceiveResetToken(string token)
    {
        try
        {
            if (!String.IsNullOrEmpty(token))
            {
                var username = (from u in db.Users
                                    where u.Userid == WebSecurity.GetUserIdFromPasswordResetToken(token)
                                    select u.Email).ToString();
                if (!String.IsNullOrEmpty(username))
                {
                    WebSecurity.ConfirmAccount(token);
                }
            }
            RedirectToAction("Index", "Home");
        }
        catch (Exception)
        {
            throw;
        }
    }

我错过了一些显而易见的东西。这个方法并不完整,因为我一直在重新思考……获取用户名,确认帐户,在不知道密码的情况下以某种方式登录,重定向到更改密码页面?感觉不对。

所以我想,也许可以把带有ViewBag的隐藏用户名传给更改对话框。。。感觉也不对劲。我想要一个更优雅的方法,接收令牌,向用户名询问新密码,更新数据库并登录。接收密码重置令牌的模式是什么?

编辑-------

因此,当我继续寻找答案时,我发现了这个小宝石。显然,有一个WebSecurity.ResetPassword方法可以接受令牌和新密码。这感觉是正确的路径,无需担心登录,只需更改并重定向到登录即可。。。我将完成代码并发布解决方案,因为这似乎是SO上一个流行且经常没有答案的问题。

如果有人能确认我走在正确的道路上,或者发表任何关于为模式添加优雅的想法,那将是很酷的

MVC4接收密码重置令牌的模式

这是一条正确的道路!

对我来说,

用户给了他电子邮件,我给他发了一个生成GUID的令牌,我有passwordResetTokenDate,当用户要求重置时,他会记下日期。(代币48小时有效)

在电子邮件中,有一个带有令牌的链接,我给他一个令牌,如果他点击时出现问题,他可以复制粘贴在文本框中的令牌,或者重新点击链接

当他点击链接时,我检查令牌和日期以及passwordResetTokenDate,如果一切正常,有两个文本框,用户输入2倍于他的新密码。

当他保存密码时,我把他记录了下来。

WebSecurity.ResetPassword做好工作!

这里有一个例子:(我有一个带有自定义提供者的自定义网络安全)

   [AllowAnonymous]
    public ActionResult ForgotMyPassword(string confirmation, string username)
    {
        username = HttpUtility.UrlDecode(username);
        ViewBag.Succeed = false;
        SetPasswordViewModel Fmp = new SetPasswordViewModel(username,confirmation);
        return View(Fmp);
    }
    //
    // POST: /Account/ForgotMyPassword
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult ForgotMyPassword(SetPasswordViewModel model)
    {
        ViewBag.Succeed = false;
        if (ModelState.isValid)
        {
            ViewBag.Succeed = WebSecurity.ResetPassword(model.UserName, model.PasswordResetToken, model.Password.NewPassword);
        }

        if (!ViewBag.Succeed)
        {
            ModelState.AddModelError("","something"); //something
        }
        return View(model);
    }

这就是它应该如何工作(在ASP安全工具包中实现)

  1. 用户点击忘记密码链接(例如打开/帐户/忘记)
  2. 在这个页面上,您询问用户的用户名(可能是他的电子邮件)
  3. 您检查该用户是否存在。如果是,则生成一个重置令牌,将其保存在该用户名的数据库中,并向该用户发送一封带有链接的电子邮件(http://yourdomain.com/account/confirm/[tokenHere])
  4. 您向用户显示一条类似"如果您有一个使用此用户名的帐户,您将很快收到一封包含重置密码说明的电子邮件"的消息。但您没有在该页面上登录用户,因为您只是要求他提供用户名
  5. 用户收到电子邮件,点击链接,重置密码页面打开(/account/confirm/[tokenHere])
  6. 在此页面上,用户需要填写密码和确认密码字段。一旦完成,您将重定向用户到登录页面(您可能会争辩说,一旦用户重置密码,您就可以直接登录;但重定向到登录似乎是大多数网站遵循的标准做法。)

回答我自己的问题,以防对任何人都有帮助。

  1. 提供一个表格,要求提供电子邮件地址以发送密码重置链接
  2. 使用WebSecurity.GeneratePasswordResetToken(email, 1440)生成令牌
  3. 通过指向令牌接收方法的链接向用户发送电子邮件
  4. 编写一个HttpGet方法来接收令牌并显示newPassword表单
  5. 表单将令牌和新密码模型发布到使用WebSecurity.ResetPassword(令牌,newPassword)的方法
  6. 重定向到登录

还没有全部写出来,但我认为这是正确的方法