跨项目使用ASP.NET Core自定义Token Provider验证失败问题排查
跨网站验证自定义DataProtectorTokenProvider生成的Token问题解决方案
问题根源
虽然两个网站都配置了相同的ApplicationName,且日志显示加密/解密使用的Key GUID和Purpose完全一致,但跨站验证失败的核心原因是:默认情况下ASP.NET Core DataProtection的密钥环存储在本地文件系统,两个网站的密钥材料完全独立。日志中的Key GUID只是密钥的标识ID,并非实际的加密密钥内容,两个站点的同ID密钥对应的加密材料不同,导致无法解密。
解决方法
1. 共享DataProtection密钥存储位置
让两个网站使用同一个持久化的密钥存储位置,确保密钥材料完全一致。常见的存储选项包括共享文件目录、Redis、Azure Blob存储等。
示例:使用共享文件目录配置
builder.Services.AddDataProtection() .SetApplicationName("Whatever") .PersistKeysToFileSystem(new DirectoryInfo(@"\\your-shared-server\data-protection-keys"));
注意:需确保两个网站的运行账户对该共享目录具备读写权限。
2. 使用统一证书加密密钥环
如果无法使用共享存储,可以用同一证书加密两个网站的密钥环。这样即使密钥存储在本地,只要证书一致,就能解密对方生成的Token。
示例:使用证书配置
var sharedCert = new X509Certificate2(@"path/to/shared-cert.pfx", "your-cert-password"); builder.Services.AddDataProtection() .SetApplicationName("Whatever") .ProtectKeysWithCertificate(sharedCert);
3. 替代方案:将Token存储到UserTokens表
如果上述DataProtection共享方案难以落地,可以改用基于数据库存储的Token验证方式:
- 自定义实现
IUserTokenProvider,将生成的Token直接存储到AspNetUserTokens表中; - 验证时从数据库读取对应Token进行校验,不再依赖DataProtection的加密解密逻辑。
这种方案无需共享密钥,但会增加数据库读写操作。
内容的提问来源于stack exchange,提问作者Richard Barraclough
相关产品推荐
相关产品推荐

