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

.NET Core 8.0升级后KeyVaultCryptoProvider.Create方法调用失败求助

.NET 8.0下Azure Key Vault生成JWT令牌的版本兼容问题

我们使用以下代码通过Azure Key Vault密钥生成JWT令牌,该方法原本同时适配.NET Core 6.0和8.0环境:

public string GenerateJwtToken(DateTime expiryDateTime, Microsoft.IdentityModel.Tokens.SecurityKey securityKey) 
{ 
    SigningCredentials signingCredentials = new SigningCredentials(securityKey,SecurityAlgorithms.RsaSha256) 
    { 
        CryptoProviderFactory = new CryptoProviderFactory { CustomCryptoProvider = new Microsoft.IdentityModel.KeyVaultExtensions.KeyVaultCryptoProvider() } 
    };

    SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor
    {
        IssuedAt = DateTime.UtcNow,
        Expires = expiryDateTime,
        SigningCredentials = signingCredentials
    };
    
    string token = new JsonWebTokenHandler().CreateToken(tokenDescriptor);    
    return token;
}

该代码在.NET Core 6.0中可正常运行,但在.NET 8.0环境下抛出MethodAccessException错误:

System.MethodAccessException: Attempt by method 'Microsoft.IdentityModel.KeyVaultExtensions.KeyVaultCryptoProvider.Create(System.String, System.Object[])' to access method 'Microsoft.IdentityModel.Tokens.CryptoProviderFactory.ShouldCacheSignatureProvider(Microsoft.IdentityModel.Tokens.SignatureProvider)' failed.
         at Microsoft.IdentityModel.KeyVaultExtensions.KeyVaultCryptoProvider.Create(String algorithm, Object[] args)
         at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateSignatureProvider(SecurityKey key, String algorithm, Boolean willCreateSignatures, Boolean cacheProvider)
         at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateForSigning(SecurityKey key, String algorithm, Boolean cacheProvider)
         at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateForSigning(SecurityKey key, String algorithm)
         at Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.CreateSignature(ReadOnlySpan`1 data, Span`1 destination, SigningCredentials signingCredentials, Int32& bytesWritten)
         at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.CreateToken(SecurityTokenDescriptor tokenDescriptor, Boolean setdefaultTimesOnTokenCreation, Int32 tokenLifetimeInMinutes)
         at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.CreateToken(SecurityTokenDescriptor tokenDescriptor)

我们尝试改用JwtSecurityToken和JwtSecurityTokenHandler.WriteToken的方式生成令牌,代码如下:

SigningCredentials signingCredentials = new SigningCredentials(new RsaSecurityKey(new Azure.Security.KeyVault.Keys.Key.ToRSA()), SecurityAlgorithms.RsaSha256);

JwtSecurityToken token = new JwtSecurityToken(claims: claims, signingCredentials: signingCredentials);

return new JwtSecurityTokenHandler().WriteToken(token);

但仍抛出CryptographicException错误:

System.Security.Cryptography.CryptographicException: Unknown error (0xc100000d)
at System.Security.Cryptography.RSABCrypt.TrySignHash(ReadOnlySpan`1 hash, Span`1 destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, Int32& bytesWritten)
at System.Security.Cryptography.RSA.SignHash(ReadOnlySpan`1 hash, Span`1 destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
at System.Security.Cryptography.RSABCrypt.SignHash(Byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
at Microsoft.IdentityModel.Tokens.AsymmetricAdapter.SignRsa(Byte[] bytes)
at Microsoft.IdentityModel.Tokens.AsymmetricAdapter.Sign(Byte[] bytes)
at Microsoft.IdentityModel.Tokens.AsymmetricSignatureProvider.Sign(Byte[] input)
at Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.CreateEncodedSignature(String input, SigningCredentials signingCredentials)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.WriteToken(SecurityToken token)

所有依赖库已更新至最新版本,请求协助解决该版本兼容问题。


解决方案

1. 替换过时的KeyVault扩展库

Microsoft.IdentityModel.KeyVaultExtensions在.NET 8中已不再兼容,需改用Azure官方的Azure.Security.KeyVault.Keys.Cryptography库处理密钥签名操作。

2. 使用CryptographyClient直接签名JWT内容

正确做法是先构建JWT的头部和载荷,生成待签名字符串,再通过CryptographyClient调用Azure Key Vault的签名接口完成签名,最后组装成完整JWT令牌。示例代码如下:

using Azure.Security.KeyVault.Keys;
using Azure.Security.KeyVault.Keys.Cryptography;
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using System.Security.Claims;

public async Task<string> GenerateJwtTokenWithKeyVaultAsync(DateTime expiryDateTime, string keyVaultKeyId, TokenCredential credential)
{
    // 构建JWT头部和载荷
    var tokenDescriptor = new SecurityTokenDescriptor
    {
        IssuedAt = DateTime.UtcNow,
        Expires = expiryDateTime,
        Subject = new ClaimsIdentity(new List<Claim>()) // 按需添加自定义声明
    };

    var tokenHandler = new JwtSecurityTokenHandler();
    var jwtToken = tokenHandler.CreateJwtSecurityToken(tokenDescriptor);
    // 生成待签名的JWT部分(头部.载荷)
    string unsignedToken = $"{jwtToken.Header.Encode()}.{jwtToken.Payload.Encode()}";
    byte[] unsignedTokenBytes = Encoding.UTF8.GetBytes(unsignedToken);

    // 调用Azure Key Vault完成签名
    var cryptoClient = new CryptographyClient(new Uri(keyVaultKeyId), credential);
    var signResult = await cryptoClient.SignDataAsync(SignatureAlgorithm.RS256, unsignedTokenBytes);

    // 组装完整JWT令牌
    string signature = Base64UrlEncoder.Encode(signResult.Signature);
    return $"{unsignedToken}.{signature}";
}

3. 依赖包版本确认

确保项目引用以下最新稳定版包:

  • Azure.Security.KeyVault.Keys
  • Azure.Identity
  • Microsoft.IdentityModel.Tokens

错误原因说明

  • 第一种错误:MethodAccessException是因为Microsoft.IdentityModel.KeyVaultExtensions内部调用了.NET 8中已改为内部访问的方法,导致权限不足。
  • 第二种错误:CryptographicException (0xc100000d)是因为Key Vault默认配置下密钥不可导出,本地无法使用导出的RSA密钥完成签名操作。

内容的提问来源于stack exchange,提问作者Renjala RK

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 21:20:06