UserManager VerifyUserTokenAsync 始终为 False

UserManager VerifyUserTokenAsync Always False

我正在像这样生成用户令牌

public async Task GenerateCode()
{

    var code = await UserManager.GenerateUserTokenAsync("heymega", new Guid("16139fcd-7ae0-449c-ad1c-f568bbe46744"));


}

然后我通过单独的请求将相同的令牌传递给另一个操作

public async Task ValidateCode(string code)
{

    var valid = await UserManager.VerifyUserTokenAsync(new Guid("16139fcd-7ae0-449c-ad1c-f568bbe46744"), "heymega", code); //Returns False

}

但是,VerifyUserTokenAsync 方法的响应始终为 false。

如果我要生成代码并在同一操作中进行验证

public async Task GenerateCode()
{

    var code = await UserManager.GenerateUserTokenAsync("heymega", new Guid("16139fcd-7ae0-449c-ad1c-f568bbe46744"));

    var valid = await UserManager.VerifyUserTokenAsync(new Guid("16139fcd-7ae0-449c-ad1c-f568bbe46744"), "heymega", code); //Returns True

}

它 returns 正确。

为什么 Verify 方法无法验证单独请求中的代码?我是否漏掉了一些明显的东西?

我拔头发几个小时后终于想通了。您需要 URL 对代码进行编码,为此我决定使用 HttpUtility class。

HttpUtility.UrlEncode(code);

在验证代码时,您不需要需要URL解码代码。

在没有使用这个之前无法解决这个问题:

 UserManager.VerifyUserTokenAsync(userId, AccountLockedOutPurpose, code).WithCurrentCulture<bool>();

.WithCurrentCulture() - 用于 ResetPasswordAsync 等所有方法)

刚刚在这个问题上耗费了 2 天时间,这可能是您遇到这种情况的另一个原因。

在您的 Startup.cs - ConfigureServices(IServiceCollection services) 方法中,确保:

services.AddAuthentication

出现在

之前
services.AddIdentity

否则对 VerifyUserTokenAsync 的调用将始终 return false

在我的情况下,我在需要时按需实例化一个 UserManager,而不是在我的启动管道中为每个 Owin 上下文生成一个。在行为方面,如果我使用创建令牌的同一 UserManager 实例验证令牌,它将 return 为真。但是如果我做了一个实际的忘记密码流程,其中验证是在一个单独的请求中,它总是错误的。

切换我的设置以便为每个 owin 上下文创建一个 UserManager 为我解决了这个问题。显然,在验证令牌时对 Owin 有一定的依赖性。

            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

不确定 OP 是否正在使用 .Net Core,但如果有人遇到这个问题并且您正在使用依赖注入,我的解决方案是将 UserManager 的范围限定为单例。

services.AddSingleton<UserManager<YourUserAccountModel>>();

我认为这是因为当用户点击收件箱中的确认邮件 link 时,一个新的 UserManager 实例被注入到控制器中,并且没有用于生成令牌的相同密钥首先。因此它无法验证令牌。

对我来说,我遇到了同样的问题。解决方案非常简单。

在我的例子中,我添加了带有白色 space 的目的,例如“电子邮件确认”。 当我删除任何白色 space "EmailConfirmation".

时问题就解决了
bool IsTokenValed = await userManager.VerifyUserTokenAsync(user, userManager.Options.Tokens.EmailConfirmationTokenProvider, "EmailConfirmation", token);