简体   繁体   English

Asp.net核心电子邮件确认有时会说InvalidToken

[英]Asp.net Core Email confirmation sometimes says InvalidToken

I am using asp.net core identity 2.1 and i am having a random issue with email confirmation, which while email confirmation sometimes says result.Error = InvalidToken . 我正在使用asp.net核心身份2.1,我有一个随机的电子邮件确认问题,虽然电子邮件确认有时会说result.Error = InvalidToken The token is also not expired. 令牌也未过期。

Note: We are using multiple servers , and we have also stored our keys in one place so that all the servers use the same keys. 注意:我们使用多个服务器 ,并且我们还将密钥存储在一个位置,以便所有服务器使用相同的密钥。

Code snippet for email confirmation. 用于确认电子邮件的代码段。

Email Confirmation 邮件确认

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>";

Verification of token 验证令牌

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;
    }

Invalid Token 令牌无效

The below token is encoded twice but we handle that situation 以下令牌编码两次,但我们处理这种情况

CfDJ8HYrrpCgcr5GvrItPOWapXRy8WF8odd%252BVKuDup7buRsl1x4agRpfgQlEIPWiBqM0Wuilu9tCv5l%252B3lNaAb89%252Fi%252B4k0y%252FH0jdXAbabz0%252FXDGA0eUrmcKdIsDFNuXeyP5ezTVmTx8t0ky9xCTXaKLAfvTsCJviETk5Ag9JbUs3l3%252BnUon6fyYOHsslJI5VKLqhMM0Sm%252BW1EE%252B%252FPEJ%252BXcn%252FPS1My%252BI1lExuF1R1hFEZScEsUCG%252Bx%252BVIFB9bzs1IoLC%252Baw%253D%253D

Any help will be appreciated, Thank you! 任何帮助将不胜感激,谢谢!

This problem seems to be basic Query String Related issue. 这个问题似乎是基本的查询字符串相关问题。 There are no pointers in your question about sample expected value and sample actual value. 您的问题中没有关于样本预期值和样本实际值的指针。 Hence I will not be able to provide you exact answer here. 因此,我无法在此提供您的确切答案。 But below two are the pointers which will certainly resolve this issue. 但是下面两个是指针肯定会解决这个问题。

There can be two issues: 可能有两个问题:

Issue 1: Original Base-64 is not restored after HtmlDecode/UrlDecode 问题1:HtmlDecode / UrlDecode后未恢复原始Base-64

These tokens are encoded as base 64 strings which may contain characters like '+'. 这些令牌被编码为base 64字符串,其中可能包含“+”等字符。

They are sent to server. 它们被发送到服务器。

Then server tries to perform HtmlDecode operation on this string, to remove the characters which were actually present in original base 64 token. 然后服务器尝试对此字符串执行HtmlDecode操作,以删除原始base 64令牌中实际存在的字符。

Eg '+' is replaced by empty string. 例如,'+'被空字符串替换。

So, the token generated after WebUtility.HtmlDecode is invalid. 因此,在WebUtility.HtmlDecode之后生成的令牌无效。 That's why you get the invalid token error 这就是你得到无效令牌错误的原因

How to check this ? You can debug and see what is the value after HtmlDecode and what is expected value. 您可以调试并查看HtmlDecode之后的值以及期望值。 If they are differing then this is root cause. 如果它们不同则这是根本原因。

Issue 2: Query string not correctly formed 问题2:查询字符串未正确形成

Multiple key value pairs in query strings are joined using '&' character. 查询字符串中的多个键值对使用“&”字符连接。 eg key1=value1&key2=value2 例如key1 = value1&key2 = value2

But some times instead of & , its encoded version &amp; 但有些时候而不是& ,它的编码版本&amp; comes in the query string. 来自查询字符串。
eg key1=value1&key2=value2 例如key1 = value1&key2 = value2

The .Net server would not be able to parse query string correctly if this is the case. 如果是这种情况,.Net服务器将无法正确解析查询字符串。

How to check this ? You can use directly read raw query string from HttpContext or HttpRequest using QueryString property and check if this is the case. 您可以使用QueryString属性直接从HttpContext或HttpRequest中读取原始查询字符串,并检查是否是这种情况。 If it is then you can either change your client to send appropriate query string (more logical and maintainable) or write some code to correct it on server side. 如果是,那么您可以更改您的客户端以发送适当的查询字符串(更逻辑和可维护)或编写一些代码以在服务器端更正它。

These pointers should help you to resolve the issue. 这些指针应该可以帮助您解决问题。

你的电子邮件确认请求会给你作为userId和你的私钥的响应,但你的令牌方法应该是不同的功能,如令牌刷新,你需要添加一些条件,如果令牌已经过期然后刷新令牌

This may not be the perfect answer, but if you just need an urgent fix and less headache, just generate a shorter disaster free token/code. 这可能不是一个完美的答案,但如果你只需要一个紧急修复而不那么头疼,只需生成一个更短的无灾难令牌/代码。

    services.AddIdentity<ApplicationUser, ApplicationRole>(options => {
        options.Tokens.PasswordResetTokenProvider = TokenOptions.DefaultEmailProvider;
        options.Tokens.EmailConfirmationTokenProvider = TokenOptions.DefaultEmailProvider;
    }).AddDefaultTokenProviders()
    .AddEntityFrameworkStores<YourDbContext>();

You should decode the confirmation code prior to passing it into the _userManager.ConfirmEmailAsync(user, code).ConfigureAwait(false) method. 您应该在将确认代码传递到_userManager.ConfirmEmailAsync(user, code).ConfigureAwait(false)方法之前对其进行解码。

You have URL encoded the confirmation code that you use in the callBackUrl; 您有URL编码您在callBackUrl中使用的确认代码; you should use WebUtility.UrlDecode(code) to decode it before attempting to use it. 在尝试使用它之前,您应该使用WebUtility.UrlDecode(code)进行解码。

我认为用户创建过程花费了太多时间点击确认之前确保检查用户创建的数据库检查确认电子邮件在sql表中是否为false

You do not need to solve this problem using identity server. 您不需要使用身份服务器来解决此问题。

When a user register add two column in your user table. 当用户注册时在用户表中添加两列。 One for verification and others for IsVerified. 一个用于验证,另一个用于IsVerified。 In verification token column add a Guid. 在验证令牌列中添加Guid。 Then generate a link with this Guid. 然后生成与此Guid的链接。 When a user clicks this link then you get the Guid inside a controller. 当用户单击此链接时,您将获得控制器内的Guid。 Then get this user using this column, then set IsVerified column to true and delete your Guid column. 然后使用此列获取此用户,然后将IsVerified列设置为true并删除Guid列。 And your user is now successfully verified. 您的用户现已成功通过验证。

If your encoded code contains '==' in the end. 如果您的编码代码最后包含'=='。 ie after urlencode or base64 encode if the code comes out like this "cm9vdA==". 即在urlencode或base64编码之后,如果代码出现像这样的“cm9vdA ==”。

decoding this will not give you the exact encoded string and will result in an invalid code. 解码这将不会给你确切的编码字符串,并将导致无效的代码。

So while generating the token check if the encoded value ends with "==". 因此,在生成令牌时检查编码值是否以“==”结尾。 If it does generate another token and the problem will be solved. 如果它确实生成另一个令牌,问题将得到解决。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM