确认电子邮件地址时令牌无效 - Asp.Net 核心

Invalid Token when confirming email address - Asp.Net Core

我偶尔会收到 "Invalid Token" 错误 userManager.ConfirmEmailAsync(user, token)。我已将问题缩小到我的 2 个 Web 服务器位于负载平衡器后面,并且生成令牌的 Web 服务器并不总是尝试确认令牌的 Web 服务器。我在另一个网站上遇到了类似的防伪令牌问题,我通过将数据保护密钥保存到磁盘并在 Web 服务器之间共享它来解决这个问题,所以我在这里尝试了类似的方法。

services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"c:\temp\API"));

然后我将密钥复制到我的其他网络服务器中的同一文件夹,但仍然没有成功。通过 AspNetCore.Identity 代码调试我可以看到在调用

时抛出异常
var unprotectedData = Protector.Unprotect(Convert.FromBase64String(token))

在 DataProtectorTokenProvider class 中。微软代码中异常的 catch 块只是

 catch
        {
            // Do not leak exception
        }

所以我决定将一个 IDataProtector 注入到我自己的 Controller 中并尝试自己进行调用。

   public UserController(Microsoft.AspNetCore.Identity.UserManager<ApplicationUser> userManager,
        SignInManager<ApplicationUser> signInManager, Microsoft.AspNetCore.Identity.RoleManager<IdentityRole> roleManager,
        ILoggerFactory loggerFactory,
         IDataProtectionProvider dataProtectionProvider) 
    {

        Protector = dataProtectionProvider.CreateProtector("DataProtectorTokenProvider");
    }

try
        {
            var unconverted = Convert.FromBase64String(request.EmailConfirmationToken);
            var unprotectedData = Protector.Unprotect(unconverted);
        }
        catch (Exception e)
        {

        }

我现在可以捕捉到 Unprotect 调用中抛出的异常,它是:

负载无效

Microsoft.AspNetCore.DataProtection.Cng.CbcAuthenticatedEncryptor.DecryptImpl(Byte* pbCiphertext, UInt32 cbCiphertext, Byte* pbAdditionalAuthenticatedData, UInt32 cbAdditionalAuthenticatedData)\r\n 在Microsoft.AspNetCore.DataProtection.Cng.Internal.CngAuthenticatedEncryptorBase.Decrypt(ArraySegment1 ciphertext, ArraySegment1 additionalAuthenticatedData)\r\n 在 Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.UnprotectCore(Byte[] protectedData, Boolean allowOperationsOnRevokedKeys, UnprotectStatus& status)\r\n 在 Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.DangerousUnprotect(Byte[] protectedData, Boolean ignoreRevocationErrors, Boolean& requiresMigration, Boolean& wasRevoked)\r\n在 Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Unprotect(Byte[] protectedData)\r\n 在 VTR.API.Controllers.UserController.d__16.MoveNext() 在 C:\Projects\Brewster.Travel\src\cres\trunk\VTR.API\src\VTR.API\Controllers\UserController.cs:第 409 行

如果我使用在同一台服务器上生成的令牌进行调用,那么它就会成功解除保护。我显然对我尝试共享数据保护密钥的方式有一些疑问,如果有人能阐明我的问题,我将不胜感激。

多亏了这里的文档,我成功地完成了这项工作:https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview

我需要在 ConfigureServices 中添加对 SetApplicationName() 的调用:

services.AddDataProtection()
          .PersistKeysToFileSystem(new DirectoryInfo(@"c:\someDirectory"))
          .SetApplicationName("myApplicationName");