我正在使用 .NET 8.0,并且在使用
Microsoft.IdentityModel.Tokens.RsaSecurityKey
语句或带有 using
的 finally
块时,大约 50% 的时间会遇到无法访问已处置对象 rsa.Dispose()
错误。如果我不使用using或finally,则根本不会出现错误。
这是我的代码:
RSA rsa = RSA.Create(); // OR using(RSA rsa = RSA.Create())
try
{
rsa.ImportParameters(new RSAParameters
{
Modulus = bytesN,
Exponent = bytesE
});
var rsaSecurityKey = new RsaSecurityKey(rsa)
{
KeyId = strKid
};
JwtConfiguration jwtConfiguration = _configurationUtil.GetJwtConfiguration("Kakao");
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = jwtConfiguration.ValidateIssuer,
ValidIssuer = jwtConfiguration.ValidIssuer,
ValidateAudience = jwtConfiguration.ValidateAudience,
ValidAudience = jwtConfiguration.ValidAudience,
ValidateLifetime = jwtConfiguration.ValidateLifetime,
RequireExpirationTime = jwtConfiguration.RequireExpirationTime,
ValidateIssuerSigningKey = jwtConfiguration.ValidateIssuerSigningKey,
IssuerSigningKey = rsaSecurityKey,
TryAllIssuerSigningKeys = jwtConfiguration.TryAllIssuerSigningKeys,
};
var tokenHandler = new JwtSecurityTokenHandler();
var claimsPrincipal = tokenHandler.ValidateToken(strIdToken, tokenValidationParameters, out SecurityToken validatedToken);
var jwtSecurityToken = validatedToken as JwtSecurityToken;
string nonce = jwtSecurityToken!.Claims.FirstOrDefault(c => c.Type == "nonce")?.Value!;
if (nonce != oauthConfiguration.Nonce)
throw new Exception("NONCE ERROR");
strId = jwtSecurityToken.Claims.FirstOrDefault(c => c.Type == "sub")?.Value!;
strEmail = jwtSecurityToken.Claims.FirstOrDefault(c => c.Type == "email")?.Value!;
}
catch (Exception e)
{
response.RESULT_CODE = "F000";
response.RESULT_MSG = e.Message;
return Page();
}
finally
{
rsa.Dispose();
}
这是我收到的确切错误消息:
IDX10511: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.RsaSecurityKey, KeyId: 'sameKid', InternalId: 'internalId'. , KeyId: sameKid
'.
Number of keys in TokenValidationParameters: '1'.
Number of keys in Configuration: '0'.
Matched key was in 'TokenValidationParameters'.
kid: 'sameKid'.
Exceptions caught:
'System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Security.Cryptography.RSABCrypt'.
at System.Security.Cryptography.RSABCrypt.GetKey()
at System.Security.Cryptography.RSABCrypt.VerifyHash(ReadOnlySpan`1 hash, ReadOnlySpan`1 signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
at Microsoft.IdentityModel.Tokens.AsymmetricAdapter.VerifyUsingSpan(Boolean isRSA, ReadOnlySpan`1 bytes, Byte[] signature)
at Microsoft.IdentityModel.Tokens.AsymmetricAdapter.VerifyRsa(Byte[] bytes, Byte[] signature)
at Microsoft.IdentityModel.Tokens.AsymmetricAdapter.Verify(Byte[] bytes, Byte[] signature)
at Microsoft.IdentityModel.Tokens.AsymmetricSignatureProvider.Verify(Byte[] input, Byte[] signature)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(Byte[] encodedBytes, Byte[] signature, SecurityKey key, String algorithm, SecurityToken securityToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(String token, JwtSecurityToken jwtToken, TokenValidationParameters validationParameters, BaseConfiguration configuration)
'.
token: '[Security Artifact of type 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken' is hidden. For more details, see https://aka.ms/IdentityModel/SecurityArtifactLogging.]'. See https://aka.ms/IDX10511 for details.
如何正确管理 RSA 对象的处置以避免此错误?
我尝试使用 using 语句和finally 块来确保正确处理 RSA 对象。我还尝试不使用 using 或 finally 来避免处置错误。
我希望签名密钥始终保持不变,从而使过程能够顺利完成并且验证能够成功。我不确定为什么 RSA 对象被处置。
像这样改变你的
rsaSecurityKey
对象
var rsaSecurityKey = new RsaSecurityKey(rsa) { KeyId = strKid, CryptoProviderFactory = new CryptoProviderFactory { CacheSignatureProviders = false } };
问题出在签名提供者的缓存上。