密码重置密码时,ASP.Net Identity“无效令牌”

时间:2017-04-14 11:59:14

标签: c# asp.net .net passwords asp.net-identity

当用户在输入新密码后尝试在重置密码屏幕上重置密码时,我们会收到无效令牌错误消息。通常这对每个人来说都很好,即使有一些像#这样的特殊字符。我们现在有一个案例,有人在重置pw屏幕上输入*他的新密码,只是因为这个特殊字符而得到此错误消息。

我现在已经尝试了几个小时的研究,找到解决方案,为什么会这样,但没有运气。我发现this solution here在用户名中存在特殊字符问题,但我们没有遇到此问题。密码中只有一个特殊字符存在问题。由于我们已经投入生产,因此我们无法在密码中禁止使用该字符。

有人知道了吗?

生成令牌控制器方法:

[HttpPost]
[AllowAnonymous]
public async Task<ActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = await _userManager.FindByNameAsync(model.Email.ToLower());
        if (user == null || !(await _userManager.IsEmailConfirmedAsync(user.UserName)))
        {
            // Don't reveal that the user does not exist or is not confirmed
            return View("ForgotPasswordConfirmation");
        }

        // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
        // Send an email with this link
        var code = await _userManager.GeneratePasswordResetTokenAsync(user.UserName);
        code = HttpUtility.UrlEncode(code);
        var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.UserName, code = code }, protocol: Request.Url.Scheme);

        await _emailService.CreateResetPasswordEmailAsync(user, callbackUrl);
        return RedirectToAction("ForgotPasswordConfirmation", "Account");
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

重置密码控制器方法:

[HttpPost]
[AllowAnonymous]
public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }

    var user = await _userManager.FindByNameAsync(model.Email.ToLower());
    if (user == null)
    {
        // Don't reveal that the user does not exist
        return RedirectToAction("ResetPasswordConfirmation", "Account");
    }

    var result = await _userManager.ResetPasswordAsync(user.UserName, HttpUtility.UrlDecode(model.Code), model.Password);
    if (result.Succeeded)
    {
        return RedirectToAction("ResetPasswordConfirmation", "Account");
    }

    AddErrors(result);
    return View();
}

1 个答案:

答案 0 :(得分:1)

问题在于您对重置令牌进行了双重编码。这里:

var code = await _userManager.GeneratePasswordResetTokenAsync(user.UserName);
code = HttpUtility.UrlEncode(code);  //<--problem is this line
var callbackUrl = Url.Action("ResetPassword", "Account", 
    new { userId = user.UserName, code = code }, protocol: Request.Url.Scheme);

您对令牌进行编码,然后Url.Action将再次执行此操作。所以解决方案是不要手动编码,让MVC为你处理它 - 只需删除第二行。

此外,另一方面,现在无需再次解码,因此您的代码将会出现:

var result = await _userManager.ResetPasswordAsync(user.UserName, 
    model.Code, model.Password);