当用户在输入新密码后尝试在重置密码屏幕上重置密码时,我们会收到无效令牌错误消息。通常这对每个人来说都很好,即使有一些像#这样的特殊字符。我们现在有一个案例,有人在重置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();
}
答案 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);