我应该丢弃X509Certificate2吗?

17

我正在使用IdentityServer4,并且想要从文件中加载签名证书。例如,

var certificate = new X509Certificate2(
        path, 
        password, 
        X509KeyStorageFlags.EphemeralKeySet);

services.AddIdentityServer()
        .AddSigningCredential(certificate)
...
certificate.Dispose();

当我从IdentityServer请求令牌时,上述代码无法工作。但是如果我删除certificate.Dispose();,它就能正常工作。

我还尝试了另一种方法。我使用证书的私钥创建了RsaSecurityKey,并将其用于添加签名凭据。在这种情况下,处理不会导致任何问题。

var rsk = new RsaSecurityKey(certificate.GetRSAPrivateKey()))

services.AddIdentityServer()
        .AddSigningCredential(rsk)
...
certificate.Dispose()
所以我的问题更普遍。我应该处理从现有证书创建的 X509Certificate2 对象吗?
来自 Microsoft Docs

从 .NET Framework 4.6 开始,此类型实现 IDisposable 接口。当您使用完该类型后,应直接或间接地处理它。

2个回答

13
通过查看.NET Core源代码,X509Certificate2及其基类X509Certificate使用类CertificatePal来处理证书。 CertificatePal类支持从各种来源创建类的对象:blob、文件、证书存储。 在创建对象时,它调用Windows CryptoAPI获取证书句柄。因此,在使用完对象后,有必要释放句柄指向的资源。好消息是,句柄存储在SafeCertContextHandle对象中,该对象保证在垃圾收集器回收X509Certificate2对象并完成调用对象的终结器之后关闭句柄。我的理解是我们不需要手动调用Dispose方法。

6
昨晚我读了下面的博客文章,它让我也开始研究这个问题: https://snede.net/the-most-dangerous-constructor-in-net/我的代码正在使用这个构造函数,但从未处理或调用“Reset”方法。在我的本地机器、开发和临时服务器上,在Microsoft用于存储“x509Certificate2”文件的各个文件夹中,我在过去一年内没有看到超过两个文件,所以我猜垃圾收集正在像你说的那样清理它们。 - Brandon Tull

5
不,应用程序运行时不应该处理证书对象,因为当请求时,IdentityServer 将尝试使用已处理的证书对象并失败。

是的,在第一种情况下这是合理的。但是使用 RsaSecurityKey,我可以处理证书。我想知道如果我正确使用证书,也许还有另一种方法。 - qwermike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接