The antiforgery token could not be decrypted 密钥 不在 key ring 中
2025-04-11Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery|An exception was thrown while deserializing the token. Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The antiforgery token could not be decrypted.
---> System.Security.Cryptography.CryptographicException: The key {cda7d38a-a2d3-411d-abbe-18057a1debcf} was not found in the key ring. For more information go to https://aka.ms/aspnet/dataprotectionwarning
iis 部署asp.net core 程序,出现这个错误,这种错误通常出现在以下几种情况中:
1. 密钥丢失或过期
ASP.NET Core 的 Data Protection 默认使用内存中的密钥(应用重启就没了)。
如果你部署在多个服务器上,没有共享 key ring,会导致 token 在 A 服务器生成但在 B 解密失败。
服务器重启、部署变更、容器销毁等也会让旧的密钥失效。
2. 跨服务器或跨实例部署未配置共享密钥
这是在负载均衡场景下常见问题。
每台服务器独立生成密钥,不能互相识别对方生成的 token
3. 使用持久化 cookie,但 key ring 不持久
比如 token 保存在 cookie 中,过了几小时请求提交,但服务端的密钥已变。
解决方案
配置 Data Protection 使用持久化存储(推荐)
默认 key 是存在内存中的。你应该配置它保存到磁盘或 Redis:
保存到文件系统(适用于单服务器)
builder.Services.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo(@"C:\keys")) .SetApplicationName("YourApp");
保存到 Redis(适用于多服务器)
builder.Services.AddDataProtection() .PersistKeysToStackExchangeRedis(redisConnection, "DataProtection-Keys") .SetApplicationName("YourApp");
SetApplicationName(),多个实例必须使用相同的名称!
但是通常我们需要用证书来加密保存到服务器的key,具体可参考以下代码
var keyPath = Path.Combine(builder.Environment.ContentRootPath, "App_Data", "DataProtectionKeys"); Directory.CreateDirectory(keyPath); // 确保密钥存储目录存在// 获取证书路径(假设 .pfx 文件放在 App_Data 文件夹下) var certificatePath = Path.Combine(builder.Environment.ContentRootPath, "App_Data", "xx.pfx"); var certificatePassword = "xxx"; // 你设置的证书密码 builder.Services.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo(keyPath)).SetApplicationName("MyWebApp").ProtectKeysWithCertificate(new X509Certificate2(certificatePath, certificatePassword)); // 使用证书加密密钥
证书的生成我们可以使用openssl,也可以使用powershell,以下为powershell生成证书
$cert = New-SelfSignedCertificate -DnsName "localhost" -CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy Exportable -NotAfter (Get-Date).AddYears(5)$pwd = ConvertTo-SecureString -String "yourPassword123" -Force -AsPlainTextExport-PfxCertificate -Cert $cert -FilePath "C:\temp\mycert.pfx" -Password $pwd