身份密码重置令牌无效
我正在编写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发送令牌并滚动自己的查询字符串解析算法 – 许多示例将每个参数拆分为’=’,这当然不包括令牌末尾的’==’。 通过使用其中一个正则表达式解决方案或只查找第一个’=’,可以轻松解决问题。