身份密码重置令牌无效

我正在编写MVC 5并使用Identity 2.0。

现在我想重置密码。 但我总是得到重置密码令牌“无效令牌”错误。

public class AccountController : Controller { public UserManager UserManager { get; private set; } public AccountController() : this(new UserManager(new UserStore(new ApplicationDbContext()))) { } 

我设置了DataProtectorTokenProvider,

  public AccountController(UserManager userManager) { //usermanager config userManager.PasswordValidator = new PasswordValidator { RequiredLength = 5 }; userManager.EmailService = new IddaaWebSite.Controllers.MemberShip.MemberShipComponents.EmailService(); var provider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider(); userManager.UserTokenProvider = new Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider(provider.Create("UserToken")) as IUserTokenProvider; UserManager = userManager; } 

我在发送邮件之前生成密码重置

  [HttpPost] [ValidateAntiForgeryToken] public async Task ManagePassword(ManageUserViewModel model) { if (Request.Form["email"] != null) { var email = Request.Form["email"].ToString(); var user = UserManager.FindByEmail(email); var token = await UserManager.GeneratePasswordResetTokenAsync(user.Id); //mail send } } 

我点击邮件链接,我得到密码重置令牌和使用

 var result = await UserManager.ResetPasswordAsync(model.UserId, model.PasswordToken, model.NewPassword); 

结果始终为false,并显示“无效令牌”。 我应该在哪里修理?

UserManager.GeneratePasswordResetTokenAsync()经常返回包含“+”字符的字符串。 如果按查询字符串传递参数,则这是原因(’+’字符是URL中查询字符串中的空格)。

尝试将model.PasswordToken空格字符model.PasswordToken为“+”字符。

 [HttpPost] [ValidateAntiForgeryToken] publicasync Task ManagePassword(ManageUserViewModel model) { if (Request.Form["email"] != null) { var email = Request.Form["email"].ToString(); var user = UserManager.FindByEmail(email); var token = await UserManager.GeneratePasswordResetTokenAsync(user.Id); //before send mail token = HttpUtility.UrlEncode(token); //mail send } } 

并且在密码重置动作解码令牌HttpUtility.UrlDecode(token);

我发现当数据库中的AspNetUsers表中的用户的SecurityStamp列为NULL时,也会出现“无效令牌”错误。 使用开箱即用的MVC 5 Identity 2.0代码时,SecurityStamp不会为NULL,但是在我们的代码中进行了一些错误时,会对AccountController进行一些自定义,清除SecurityStamp字段中的值。

这里的许多答案在发送之前对令牌进行URLEncode以解决令牌(作为基本64位编码的字符串)通常包含“+”字符的事实。 解决方案还必须考虑令牌以’==’结尾。

我正在努力解决这个问题,结果发现大型组织中的许多用户使用的是Scanmail Trustwave Link Validator(r),它不是对称编码和解码电子邮件链接中的URLEncoded stings(在撰写本文时)。

最简单的方法是使用Mateusz Cisek的答案并发送一个非URLEncoded令牌,只需将空格字符替换回+。 在我的情况下,这是在角度SPA中完成的,因此Javascript变为$routeParams.token.replace(/ /g,'+')

这里需要注意的是,如果使用AJAX发送令牌并滚动自己的查询字符串解析算法 – 许多示例将每个参数拆分为’=’,这当然不包括令牌末尾的’==’。 通过使用其中一个正则表达式解决方案或只查找第一个’=’,可以轻松解决问题。