【问题标题】:RSA Disposed Object Error - every other testRSA Disposed Object Error - 每隔一个测试
【发布时间】:2023-04-05 22:50:01
【问题描述】:

我们有几个测试会生成一个 jwt 请求来调用服务器来检索令牌。我们有 6 个测试使用相同的数据对相同的方法进行相同的调用。这是方法: '''

    private static string GenerateSignedTokenRequest(
        string privateKey,
        string privateKeyPass,
        string clientID,
        string audience,
        int lifetime)
    {
        var jti = Guid.NewGuid().ToString();

        var claims = new[]
        {
            new Claim(JwtRegisteredClaimNames.Jti, jti),
            new Claim(JwtRegisteredClaimNames.Sub, clientID),
        };

        var decodedKey = DecodeRsaPrivateKeyFromPem(
            privateKey,
            privateKeyPass);

        var priDecKey = decodedKey.Private as RsaPrivateCrtKeyParameters;

        var rsaParams = DotNetUtilities.ToRSAParameters(priDecKey);

        using (var rsa = RSA.Create(rsaParams))
        {

            var token = new JwtSecurityToken(
                clientID,
                audience,
                claims,
                DateTime.Now.AddMinutes(-1),
                DateTime.Now.AddSeconds(lifetime),
                new SigningCredentials(
                    new RsaSecurityKey(rsa),
                    SecurityAlgorithms.RsaSha256));

            return new JwtSecurityTokenHandler().WriteToken(token);
        }

    }

'''

在 WriteToken(token) 方法上运行的所有其他测试中,我们都会收到以下错误: {"无法访问已释放的对象。\r\n对象名称:'RSA'。"}

令人困惑的是,每个奇数测试都可以很好地运行此代码,但每个偶数测试都失败了。但是当我单独重新运行每个测试时,它们都是绿色的。只有当我将它们全部一起运行时,其他所有测试都失败了。

从 .Net Core 和测试框架从 3.1.0 迁移到 3.1.4 时发生这种情况

enter image description here

【问题讨论】:

  • 不确定你的意思。这在 Visual Studio 中编译得很好。结束括号就在分号之前。 var token = new JwtSecurityToken(clientID, Audience, Claims, DateTime.Now.AddMinutes(-1), DateTime.Now.AddSeconds(lifetime), new SigningCredentials( new RsaSecurityKey(rsa), SecurityAlgorithms.RsaSha256));
  • 啊,我错过了。

标签: c# .net-core jwt rsa


【解决方案1】:

所以看来问题是针对 .Net 的 Windows Azure Active Directory IdentityModel Extensions 的升级。似乎有一个缓存不受在 RSA.Create() 方法周围使用 using 的影响。通过删除 using 所有测试都是绿色的。

以下是一些有助于我诊断的链接: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc

还有:

https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/1433

【讨论】:

  • 禁用第二个链接建议的缓存解决了我的问题。
【解决方案2】:

更新这个

new SigningCredentials(
                new RsaSecurityKey(rsa),
                SecurityAlgorithms.RsaSha256)

new SigningCredentials(
                new RsaSecurityKey(rsa),
                SecurityAlgorithms.RsaSha256){
            CryptoProviderFactory = new CryptoProviderFactory { CacheSignatureProviders = false }
        }

参考:https://vmsdurano.com/-net-core-3-1-signing-jwt-with-rsa/

【讨论】:

  • 感谢分享!这在 .Net core 3.1 中对我有用
【解决方案3】:

下面的代码对我来说非常好。 在下面的代码中,我将声明作为参数并从配置中提取证书。无需将私钥设置为变量,而是直接放入密钥即可解决问题。

using (X509Certificate2 certificate = new X509Certificate2(certPath, tokenConfig["CertSecret"], System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.PersistKeySet))
{

    if (certificate.HasPrivateKey)
       {
    var signingCredentials = new SigningCredentials(
                   key: new RsaSecurityKey((RSA)certificate.PrivateKey),
                                algorithm: SecurityAlgorithms.RsaSha256 
                            );
    
                        var token = new JwtSecurityToken(
                            claims: claims,
                            expires: DateTime.Now.AddMinutes(Convert.ToInt32(configuration["TokenMinutesToExpire"])),
                            signingCredentials: signingCredentials);
                        return $"Bearer {new JwtSecurityTokenHandler().WriteToken(token)}";
                    }
       }

}

【讨论】:

  • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-28
  • 1970-01-01
  • 2012-11-03
相关资源
最近更新 更多