我正在编写MVC 5并使用Identity 2.0。
现在我正在尝试重置密码。但是我总是收到重置密码令牌的"无效令牌"错误。
public class AccountController : Controller
{
public UserManager<ApplicationUser> UserManager { get; private set; }
public AccountController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
{
}
我设置了DataProtectorTokenProvider,
public AccountController(UserManager<ApplicationUser> 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<ApplicationUser>(provider.Create("UserToken"))
as IUserTokenProvider<ApplicationUser, string>;
UserManager = userManager;
}
我在发送邮件之前生成密码重置
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> 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);
结果总是假的,它说"无效令牌"。我应该在哪里修复?
UserManager.GeneratePasswordResetTokenAsync()
经常返回包含"+"字符的字符串。如果通过查询字符串传递参数,这就是原因("+"字符是 URL 中查询字符串中的空格)。
尝试将model.PasswordToken
中的空格字符替换为"+"字符。
[HttpPost]
[ValidateAntiForgeryToken]
publicasync Task<ActionResult> 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 字段中的值。
这里有很多答案 URL 在发送之前对令牌进行编码,以解决令牌(作为 base 64 编码字符串)通常包含"+"字符的事实。解决方案还必须考虑到令牌以"=="结尾。
我一直在为这个问题而苦苦挣扎,事实证明,大型组织中的许多用户都在使用Scanmail Trustwave Link Validator(r),它不是对称编码和解码电子邮件链接中的URLEncodes(在撰写本文时)。
最简单的方法是使用 Mateusz Cisek 的答案并发送一个非 URLEncoding 的令牌,并简单地将空格字符替换回 +。在我的情况下,这是在角度SPA中完成的,因此Javascript变得$routeParams.token.replace(/ /g,'+')
。
这里需要注意的是,如果使用 AJAX 发送令牌并滚动您自己的查询字符串解析算法 - 许多示例将每个参数拆分为"=",当然不会在令牌末尾包含"=="。通过使用正则表达式解决方案之一或仅查找第一个"=",易于解决。