密码重置密码时,ASP.Net Identity“无效令牌”(ASP.Net Identity “Invalid token” on password reset with * in password

系统教程 行业动态 更新时间:2024-06-14 16:54:47
密码重置密码时,ASP.Net Identity“无效令牌”(ASP.Net Identity “Invalid token” on password reset with * in password)

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

我现在已经尝试了几个小时的研究来找到解决方案,为什么会发生这种情况,但没有运气。 我在这里找到了这个解决方案,其中包含用户名中的特殊字符问题,但我们没有这个问题。 密码中只有一个特殊字符存在问题。 由于我们已经在制作中,因此我们不能仅仅在密码中禁止使用该字符。

有人知道了吗?

生成令牌控制器方法:

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

We get the invalid token error messages when a user tries to reset his password on the reset password screen after entering the new password. Normally this works just fine for everyone even with some special character like #. We have now a case where someone puts in * in his new password on the reset pw screen, gets this error message just because of this special character.

I've tried hours of research now to find a solution to why this happens but with no luck. I've found this solution here which has an issue with special characters in the username but we don't have that issue. There is only an issue with that special character in the password. As we are already in production we can't just disallow that character in passwords.

Someone got a clue?

Generating the token controller method:

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

Reset password controller method:

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

最满意答案

问题是您要对重置令牌进行双重编码。 这里:

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

The problem is that you are double encoding the reset token. Here:

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

you encode the token and then Url.Action will do it again. So the solution is to not encode manually and let MVC handle it for you - just remove the second line here.

Also, on the other end, there's now no need to decode again, so your code there will be:

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

更多推荐

本文发布于:2023-04-08 12:37:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/dzcp/6e56de947f225551be4949b3404a6bc6.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:密码   令牌   Net   ASP   reset

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!