[英]ASP.Net Core Identity ResetPasswordAsync Failed : InvalidToken
[英]Asp.net Core Email confirmation sometimes says InvalidToken
我正在使用asp.net核心身份2.1,我有一个随机的电子邮件确认问题,虽然电子邮件确认有时会说result.Error = InvalidToken 。 令牌也未过期。
注意:我们使用多个服务器 ,并且我们还将密钥存储在一个位置,以便所有服务器使用相同的密钥。
用于确认电子邮件的代码段。
邮件确认
var confCode = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Action("ConfirmEmail", "Account", new
{
userId = user.Id,
code = WebUtility.UrlEncode(confCode)
}, protocol: HttpContext.Request.Scheme);
string confirmationEmailBody = string.Format(GetTranslatedResourceString("ConfirmationEmailBody"), "<a href='" + callbackUrl + "'>") + "</a>";
验证令牌
public async Task<bool> ConfirmEmailAsync(string userId, string code)
{
if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(code))
return false;
var user = await _userManager.FindByIdAsync(userId);
if (user == null)
return false;
var result = await _userManager.ConfirmEmailAsync(user, code).ConfigureAwait(false);
if (!result.Succeeded)
result = await _userManager.ConfirmEmailAsync(user, WebUtility.UrlDecode(code)).ConfigureAwait(false);
return result.Succeeded;
}
令牌无效
以下令牌编码两次,但我们处理这种情况
CfDJ8HYrrpCgcr5GvrItPOWapXRy8WF8odd%252BVKuDup7buRsl1x4agRpfgQlEIPWiBqM0Wuilu9tCv5l%252B3lNaAb89%252Fi%252B4k0y%252FH0jdXAbabz0%252FXDGA0eUrmcKdIsDFNuXeyP5ezTVmTx8t0ky9xCTXaKLAfvTsCJviETk5Ag9JbUs3l3%252BnUon6fyYOHsslJI5VKLqhMM0Sm%252BW1EE%252B%252FPEJ%252BXcn%252FPS1My%252BI1lExuF1R1hFEZScEsUCG%252Bx%252BVIFB9bzs1IoLC%252Baw%253D%253D
任何帮助将不胜感激,谢谢!
这个问题似乎是基本的查询字符串相关问题。 您的问题中没有关于样本预期值和样本实际值的指针。 因此,我无法在此提供您的确切答案。 但是下面两个是指针肯定会解决这个问题。
可能有两个问题:
问题1:HtmlDecode / UrlDecode后未恢复原始Base-64
这些令牌被编码为base 64字符串,其中可能包含“+”等字符。
它们被发送到服务器。
然后服务器尝试对此字符串执行HtmlDecode操作,以删除原始base 64令牌中实际存在的字符。
例如,'+'被空字符串替换。
因此,在WebUtility.HtmlDecode之后生成的令牌无效。 这就是你得到无效令牌错误的原因
How to check this ?
您可以调试并查看HtmlDecode之后的值以及期望值。 如果它们不同则这是根本原因。
问题2:查询字符串未正确形成
查询字符串中的多个键值对使用“&”字符连接。 例如key1 = value1&key2 = value2
但有些时候而不是&
,它的编码版本&
来自查询字符串。
例如key1 = value1&key2 = value2
如果是这种情况,.Net服务器将无法正确解析查询字符串。
How to check this ?
您可以使用QueryString属性直接从HttpContext或HttpRequest中读取原始查询字符串,并检查是否是这种情况。 如果是,那么您可以更改您的客户端以发送适当的查询字符串(更逻辑和可维护)或编写一些代码以在服务器端更正它。
这些指针应该可以帮助您解决问题。
你的电子邮件确认请求会给你作为userId和你的私钥的响应,但你的令牌方法应该是不同的功能,如令牌刷新,你需要添加一些条件,如果令牌已经过期然后刷新令牌
这可能不是一个完美的答案,但如果你只需要一个紧急修复而不那么头疼,只需生成一个更短的无灾难令牌/代码。
services.AddIdentity<ApplicationUser, ApplicationRole>(options => {
options.Tokens.PasswordResetTokenProvider = TokenOptions.DefaultEmailProvider;
options.Tokens.EmailConfirmationTokenProvider = TokenOptions.DefaultEmailProvider;
}).AddDefaultTokenProviders()
.AddEntityFrameworkStores<YourDbContext>();
您应该在将确认代码传递到_userManager.ConfirmEmailAsync(user, code).ConfigureAwait(false)
方法之前对其进行解码。
您有URL编码您在callBackUrl中使用的确认代码; 在尝试使用它之前,您应该使用WebUtility.UrlDecode(code)
进行解码。
我认为用户创建过程花费了太多时间点击确认之前确保检查用户创建的数据库检查确认电子邮件在sql表中是否为false
您不需要使用身份服务器来解决此问题。
当用户注册时在用户表中添加两列。 一个用于验证,另一个用于IsVerified。 在验证令牌列中添加Guid。 然后生成与此Guid的链接。 当用户单击此链接时,您将获得控制器内的Guid。 然后使用此列获取此用户,然后将IsVerified列设置为true并删除Guid列。 您的用户现已成功通过验证。
如果您的编码代码最后包含'=='。 即在urlencode或base64编码之后,如果代码出现像这样的“cm9vdA ==”。
解码这将不会给你确切的编码字符串,并将导致无效的代码。
因此,在生成令牌时检查编码值是否以“==”结尾。 如果它确实生成另一个令牌,问题将得到解决。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.