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

时间:2013-08-10 18:53:04

标签: c# asp.net-mvc-4 passwords

尝试获取密码重置功能。这将适用于没有也无法登录系统的用户。我觉得我很接近,但感觉不对:

我有一个ResetPassword方法/视图...它只是询问用户的电子邮件地址,不向用户确认帐户,但如果存在,则发送带有链接+令牌的电子邮件。一切正常。

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

[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方法接受令牌和新密码。这感觉就像正确的道路,无需担心登录,只需更改它并重定向登录......我将完成代码并发布一个解决方案,因为这似乎是一个流行的,往往没有答案的问题。 / p>

如果有人能证实我正走在正确的道路上或发布任何关于为这种模式添加优雅的想法

3 个答案:

答案 0 :(得分:2)

这是一条正确的道路!

对我来说,

用户发送他的电子邮件,然后我向他发送一个令牌,该令牌生成GUID并且我passwordResetTokenDate在用户要求重置时选择日期。 (令牌有效48小时)

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

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

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

WebSecurity.ResetPassword做好工作!

这里有一个例子:(我有自定义提供商的自定义websecurity)

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

答案 1 :(得分:1)

这是它应该如何工作(在ASP Security Kit中实现)

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

答案 2 :(得分:1)

回答我自己的问题以防万一。

  1. 提供要求发送密码重置链接的电子邮件地址的表单
  2. 使用WebSecurity.GeneratePasswordResetToken(email, 1440)生成令牌
  3. 向用户发送电子邮件,其链接指向令牌接收方式
  4. 编写HttpGet方法以接收令牌并显示newPassword表单
  5. 表单将令牌和新密码模型发布到使用WebSecurity.ResetPassword(token,newPassword)的方法
  6. 重定向登录
  7. 尚未完全写出来,但我认为这是正确的方法