我正在使用Asp.Net-Identity-2,并试图使用以下方法验证电子邮件验证代码。但是我得到了一个“无效令牌”错误消息。
我不知道会错过什么或者什么不对劲..。
发布于 2014-08-20 13:28:46
因为您正在为密码重置生成令牌:
string code = UserManager.GeneratePasswordResetToken(user.Id);但实际上试图验证电子邮件的令牌:
result = await UserManager.ConfirmEmailAsync(id, code);这是两个不同的记号。
在您的问题中,您说您正在试图验证电子邮件,但您的代码是密码重置。你在做哪一个?
如果需要电子邮件确认,则通过以下方式生成令牌
var emailConfirmationCode = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);并通过
var confirmResult = await UserManager.ConfirmEmailAsync(userId, code);如果需要重置密码,请生成如下令牌:
var code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);并以如下方式确认:
var resetResult = await userManager.ResetPasswordAsync(user.Id, code, newPassword);发布于 2015-03-11 10:17:33
我遇到了这个问题并解决了它。有几个可能的原因。
1. URL-编码问题(如果问题“随机”发生)
如果这种情况是随机发生的,您可能会遇到url编码问题。由于未知的原因,令牌不是为url安全设计的,这意味着它在通过url传递时可能包含无效字符(例如,通过电子邮件发送)。
在这种情况下,应该使用HttpUtility.UrlEncode(token)和HttpUtility.UrlDecode(token)。
正如o o Pereira在他的评论中所说的,UrlDecode不是(或者有时不是?)必填项。请两样都试试。谢谢。
2.非匹配方法(电子邮件与密码标记)
例如:
var code = await userManager.GenerateEmailConfirmationTokenAsync(user.Id);和
var result = await userManager.ResetPasswordAsync(user.Id, code, newPassword);电子邮件令牌提供程序生成的令牌不能由重置密码令牌提供程序确认.
但我们将看到这种情况发生的根本原因。
3.令牌提供者的不同实例
即使您正在使用:
var token = await _userManager.GeneratePasswordResetTokenAsync(user.Id);随同
var result = await _userManager.ResetPasswordAsync(user.Id, HttpUtility.UrlDecode(token), newPassword);这个错误仍有可能发生。
我的旧代码说明了为什么:
public class AccountController : Controller
{
private readonly UserManager _userManager = UserManager.CreateUserManager();
[AllowAnonymous]
[HttpPost]
public async Task<ActionResult> ForgotPassword(FormCollection collection)
{
var token = await _userManager.GeneratePasswordResetTokenAsync(user.Id);
var callbackUrl = Url.Action("ResetPassword", "Account", new { area = "", UserId = user.Id, token = HttpUtility.UrlEncode(token) }, Request.Url.Scheme);
Mail.Send(...);
}以及:
public class UserManager : UserManager<IdentityUser>
{
private static readonly UserStore<IdentityUser> UserStore = new UserStore<IdentityUser>();
private static readonly UserManager Instance = new UserManager();
private UserManager()
: base(UserStore)
{
}
public static UserManager CreateUserManager()
{
var dataProtectionProvider = new DpapiDataProtectionProvider();
Instance.UserTokenProvider = new DataProtectorTokenProvider<IdentityUser>(dataProtectionProvider.Create());
return Instance;
}注意,在这段代码中,每次创建UserManager (或new-ed)时,都会生成一个新的dataProtectionProvider。因此,当用户收到电子邮件并单击链接时:
public class AccountController : Controller
{
private readonly UserManager _userManager = UserManager.CreateUserManager();
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ResetPassword(string userId, string token, FormCollection collection)
{
var result = await _userManager.ResetPasswordAsync(user.Id, HttpUtility.UrlDecode(token), newPassword);
if (result != IdentityResult.Success)
return Content(result.Errors.Aggregate("", (current, error) => current + error + "\r\n"));
return RedirectToAction("Login");
}AccountController不再是旧的,_userManager及其令牌提供程序也不再是旧的。因此,新的令牌提供程序将失败,因为它的内存中没有该令牌。
因此,我们需要为令牌提供程序使用一个实例。这是我的新代码,它运行得很好:
public class UserManager : UserManager<IdentityUser>
{
private static readonly UserStore<IdentityUser> UserStore = new UserStore<IdentityUser>();
private static readonly UserManager Instance = new UserManager();
private UserManager()
: base(UserStore)
{
}
public static UserManager CreateUserManager()
{
//...
Instance.UserTokenProvider = TokenProvider.Provider;
return Instance;
}以及:
public static class TokenProvider
{
[UsedImplicitly] private static DataProtectorTokenProvider<IdentityUser> _tokenProvider;
public static DataProtectorTokenProvider<IdentityUser> Provider
{
get
{
if (_tokenProvider != null)
return _tokenProvider;
var dataProtectionProvider = new DpapiDataProtectionProvider();
_tokenProvider = new DataProtectorTokenProvider<IdentityUser>(dataProtectionProvider.Create());
return _tokenProvider;
}
}
}它不能说是一个优雅的解决方案,但它触及了根源,解决了我的问题。
发布于 2015-04-28 17:45:19
即使使用这样的代码,我也会得到“无效令牌”错误:
var emailCode = UserManager.GenerateEmailConfirmationToken(id);
var result = UserManager.ConfirmEmail(id, emailCode);在我的例子中,问题是,在不使用UserManager.Create(...) 方法的情况下,我手动创建用户并将其添加到数据库中。用户存在于数据库中,但没有安全标记。
有趣的是,GenerateEmailConfirmationToken返回一个令牌而不抱怨缺少安全标记,但该令牌永远无法验证。
https://stackoverflow.com/questions/25405307
复制相似问题