使用 ASP.NET 身份重置密码时令牌无效

Posted

技术标签:

【中文标题】使用 ASP.NET 身份重置密码时令牌无效【英文标题】:Token invalid on reset password with ASP.NET Identity 【发布时间】:2015-01-30 05:47:44 【问题描述】:

我通过从 VS 2013 模板复制代码,在我的 MVC 应用程序中实现了 ASP.NET Identity。基本工作正常,但我无法让重置密码工作。当我显示“忘记密码”页面时,会生成一封包含令牌的电子邮件。此令牌由方法返回:

UserManager.GeneratePasswordResetTokenAsync(user.Id)

当我点击链接时,重置密码表单打开,让用户输入他们的电子邮件地址和新密码。然后调用更改密码功能:

UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);

这对我来说看起来不错,但结果总是“无效令牌”,我不明白为什么会这样。

有人知道它为什么不起作用吗?令牌到底存储在哪里?我认为它一定在数据库中 AspNetUsers 表周围的某个地方...

【问题讨论】:

【参考方案1】:

UserManager 在 ASP.NET 标识中生成的令牌通常包含“+”字符,当作为查询字符串传递时,会在 URL 中更改为“”(空格)。在您的 ResetPassword ActionResult 中,将“”替换为“+”,如下所示:

var code = model.Code.Replace(" ", "+");
//And then change the following line 
UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);
//To this one so it uses the code(spaces replaced with "+") instead of model.Code
UserManager.ResetPasswordAsync(user.Id, code, model.Password);

这应该可以解决问题。 我遇到了同样的问题,找到了答案here。

【讨论】:

对我来说,当其他答案中描述的 UrlEncode/Decode 没有时,这有效。 我也是同样的问题,我无法从代码的最后一端获取“==”,所以如何处理这个我是通过邮件中的查询字符串发送的代码,我也试试这个 WebUtility。邮件中的 UrlEncode(code) 发送和获取时间 WebUtility.UrDecode(Model.code) 使用此但仍然遇到问题并结束获取无效令牌。 这救了我两次 @Mansoor 你对我的this 帖子有什么建议吗?我尝试了您的上述建议,但没有奏效。 真的很好奇为什么解码也不适合我。这个答案确实有效,让我省了很多麻烦,因为令牌并不总是用那个符号生成的。【参考方案2】:

只是想补充一点,除了 html 编码/解码之外,最常见的问题是您在数据库中的用户条目可能缺少 SecurityStamp。 ASP.NET Identity 中存在一个错误,其中一个函数在创建令牌时将其设置为 null,而另一个在验证令牌时会检查空字符串。

如果您的 SecurityStamp 为 null 或空字符串,这将导致无效令牌问题。

【讨论】:

这也是我的问题。我刚刚用一个随机字符串更新了空值,它似乎对此很满意!大量的咒骂和愤怒蔓延开来。我欠你的债。 感谢这解决了我的问题,由于在我们大多数用户之后添加了 SecurityToken,这似乎是相同的,但是当添加新用户时呢?他们最初会获得一个有效的安全令牌吗? 这解决了我的问题 - 只需运行 UPDATE [AspNetUsers] SET [SecurityStamp] = NEWID() WHERE [SecurityStamp] IS NULL 来填写 NULL,然后就可以正常工作了。 但是我们如何防止它再次发生呢? null SecurityStamp 是我的问题。谢谢!【参考方案3】:

对我来说,安全印章没问题。与接受的答案一致,我使用编码方法使用HttpContext.Current.Server.UrlEncode 对带有重置链接的代码进行编码,如下所示:

string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
string callbackUrl = ConfigurationManager.AppSettings["baseurl"] + "/resetpassword?email=" + user.Email + "&code=" + HttpContext.Current.Server.UrlEncode(code);

【讨论】:

【参考方案4】:

如果您的SecurityStamp 在生成令牌后发生更改,则该令牌也无效。

例如,您使用生成令牌

UserManager.GeneratePasswordResetTokenAsync(user.Id);

然后调用

UserManager.RemovePasswordAsync(user.Id);

您的SecurityStamp 得到更新,因此令牌现在无效

【讨论】:

【参考方案5】:

在我的情况下,这是因为数据库中的数据错误地从另一个数据库导入。 SecurityStamp 字段为空,所以我收到无效令牌错误。

【讨论】:

删除了该特定表的数据导入,而是使用 UserManager 从旧数据库创建用户。 @TylerJamesHarden 我不记得了,也许我没有先阅读你的答案就发布了我的答案。顺便说一句,很抱歉给您带来任何不便。 我遇到了这个问题,为了创建正确的有效令牌,我在用户的安全标记字段中放置了新的 GUID。一旦我这样做了,它就开始工作了

以上是关于使用 ASP.NET 身份重置密码时令牌无效的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core 2.2 - 密码重置在 Azure 上不起作用(无效令牌)

身份密码重置令牌无效

如何检查密码重置令牌是不是已过期?

ASP.NET Core Identity - 使令牌(电子邮件确认、密码重置等)在不同服务器上有效?

如何从 ASP.NET Core 中的密码重置令牌中检索用户?

ASP.NET 核心中的密码重置令牌提供程序 - 找不到 IUserTokenProvider