在 C# 中使用 JwtSecurityTokenHandler 验证 JWT 时如何解决 RSA 处置错误

问题描述 投票:0回答:1

我正在使用 .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 对象被处置。

c# validation .net-core jwt rsa
1个回答
0
投票

像这样改变你的

rsaSecurityKey
对象

 var rsaSecurityKey = new RsaSecurityKey(rsa) { KeyId = strKid, CryptoProviderFactory = new CryptoProviderFactory { CacheSignatureProviders = false } };

问题出在签名提供者的缓存上。

© www.soinside.com 2019 - 2024. All rights reserved.