You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Identity Server 4升级到Duende IS6后登录抛出密钥不存在异常

问题分析与解决方案

关于Keys SQL表的疑问

不需要将密钥持久化到Keys SQL表——你已经通过options.KeyManagement.Enabled = false禁用了Duende IdentityServer的密钥管理功能,此时系统会直接使用你手动提供的签名凭据,不会依赖内置的密钥存储机制。

报错根源

你当前代码中keyResponse.Value.Key.ToRSA()返回的是RSACng实例,它依赖Windows CNG(加密下一代技术)的本地密钥句柄。本地开发环境中这个句柄可以正常工作,但部署后(比如IIS应用池场景),会因为进程隔离、权限限制或远程密钥引用失效等问题,导致签名时找不到对应的密钥,从而抛出WindowsCryptographicException: Key does not exist。

另外,Azure Key Vault的密钥默认是不可导出的,ToRSA()并没有真正将私钥下载到本地,只是创建了一个指向远程KV的CNG密钥引用,这种引用在部署环境中往往无法正常完成签名操作。

具体解决方案

方案1:使用Azure Key Vault CryptographyClient完成签名(推荐)

这种方式无需将密钥下载到本地,所有签名操作直接通过Azure Key Vault服务完成,彻底避免本地密钥句柄问题。

修改代码如下:

var identityServiceBuild = services.AddIdentityServer(options =>
{
    options.KeyManagement.Enabled = false;
});

string keyVaultName = "mykeyvault";
var kvUri = new Uri($"https://{keyVaultName}.vault.azure.net");

// 创建KeyClient与CryptographyClient
var keyClient = new KeyClient(kvUri, new DefaultAzureCredential());
var keyResponse = await keyClient.GetKeyAsync("devidentityserver");
var cryptoClient = new CryptographyClient(keyResponse.Value.Id, new DefaultAzureCredential());

// 创建基于Azure KV的签名凭据
var signingCredentials = new SigningCredentials(
    new AzureSecurityKey(cryptoClient),
    IdentityServerConstants.RsaSigningAlgorithm.RS256)
{
    KeyId = keyResponse.Value.Properties.Version
};

identityServiceBuild.AddSigningCredential(signingCredentials);

注意事项:

  • 需要安装Azure.Security.KeyVault.Cryptography NuGet包
  • 确保部署环境使用的身份(如应用服务托管身份)拥有Azure Key Vault的Key Sign权限

方案2:导出密钥并创建本地RSA实例(仅适用于可导出密钥)

如果你的Azure Key Vault密钥创建时设置了KeyExportPolicy.AllowExport(允许导出私钥),可以将密钥参数导出到本地内存中初始化RSA实例:

var identityServiceBuild = services.AddIdentityServer(options =>
{
    options.KeyManagement.Enabled = false;
});

string keyVaultName = "mykeyvault";
var kvUri = new Uri($"https://{keyVaultName}.vault.azure.net");

var keyClient = new KeyClient(kvUri, new DefaultAzureCredential());
var keyResponse = await keyClient.GetKeyAsync("devidentityserver");

// 导出私钥参数并初始化本地RSA
var rsaParams = keyResponse.Value.Key.ToRSA().ExportParameters(true);
var rsa = RSA.Create();
rsa.ImportParameters(rsaParams);

var key = new RsaSecurityKey(rsa) { KeyId = keyResponse.Value.Properties.Version };
identityServiceBuild.AddSigningCredential(key, IdentityServerConstants.RsaSigningAlgorithm.RS256);

⚠️ 风险提示:此方式会将私钥加载到应用内存中,存在安全泄露风险,仅在必要场景下使用,同时需严格控制Key Vault的访问权限。

额外排查点

  • 确认部署环境的身份拥有对应Key Vault权限(方案1需Key Sign,方案2需Key Get+Key Export)
  • 检查Azure Key Vault的网络配置,确保部署环境(如应用服务、虚拟机)可以访问KV(正确配置防火墙、虚拟网络对等)
  • IIS部署场景下,确认应用池身份拥有访问Windows CNG资源的权限(方案2适用)

内容的提问来源于stack exchange,提问作者Andrew Duffy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 13:08:15