我们有以下代码片段,用于使用 Azure KeyVault 密钥生成令牌。 .net core 6.0 和 .net core 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中,它可以正常工作,没有任何错误,但在8.0中它会抛出以下错误。
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(token) 生成密钥的不同方法。下面是结果,我们结束了
System.Security.Cryptography.CryptographicException:未知错误(0xc100000d) 在 System.Security.Cryptography.RSABCrypt.TrySignHash(ReadOnlySpan
1 hash, Span
1 目的地,HashAlgorithmName hashAlgorithm,RSASignaturePadding 填充,Int32& bytesWritten)
在 System.Security.Cryptography.RSA.SignHash(ReadOnlySpan1 hash, Span
1 目的地,HashAlgorithmName hashAlgorithm,RSASignaturePadding 填充)
在 System.Security.Cryptography.RSABCrypt.SignHash(Byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding 填充)
在 Microsoft.IdentityModel.Tokens.AmetryAdapter.SignRsa(Byte[] 字节)
在 Microsoft.IdentityModel.Tokens.AmetryAdapter.Sign(Byte[] 字节)
在 Microsoft.IdentityModel.Tokens.AmetrySignatureProvider.Sign(Byte[] 输入)
在 Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.CreateEncodedSignature(字符串输入,SigningCredentials 签名Credentials)
在 System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.WriteToken(SecurityToken 令牌)
使用的代码片段在这里
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);
我需要一些帮助来减轻这个版本的混乱。
如果需要更多详细信息,请告诉我。 请注意:所有必需的库都已更新到最新的可用版本。
问题解决了。当您从 Azure KeyVault 检索 KeyVaultKey 值时,同时创建 CryptographyClient。
keyClient = new(vaultUri: new Uri(keyVaultUri), credential: new DefaultAzureCredential(new DefaultAzureCredentialOptions()
{
AdditionallyAllowedTenants = { tenatId }
}));
cryptoClient = new CryptographyClient(keyClient.GetKey(keyName).Value.Id, new DefaultAzureCredential(new DefaultAzureCredentialOptions()
{
AdditionallyAllowedTenants = { tenatId }
}));
然后在逻辑方面使用下面
JwtSecurityToken token = new(claims: claims, notBefore: iat, expires: expiryDateTime, signingCredentials: new SigningCredentials(new RsaSecurityKey(adminSettings.PRDCryptoClient.CreateRSA()), SecurityAlgorithms.RsaSha256));
return new JwtSecurityTokenHandler().WriteToken(token);
这解决了问题。但我认为微软必须解决库问题才能回到之前的“SecurityKey”基于类的方法。