确认电子邮件地址时令牌无效 - 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, ArraySegment
1 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");
我偶尔会收到 "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, ArraySegment
1 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");