我应该处理 X509Certificate2 吗?

Posted

技术标签:

【中文标题】我应该处理 X509Certificate2 吗?【英文标题】:Should I dispose of X509Certificate2? 【发布时间】:2019-10-13 16:48:41 【问题描述】:

我正在使用 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 接口。当您使用完该类型后,您应该直接或间接地处理它。

【问题讨论】:

【参考方案1】:

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

【讨论】:

我昨晚阅读了下面的博客文章,它也让我研究了这个问题:snede.net/the-most-dangerous-constructor-in-net 我的代码正在使用构造函数,从不释放或调用 Reset 方法。在我的本地机器、开发和登台服务器上,在过去一年中,我在 Microsoft 用来存储 x509Certficate2 文件的各种文件夹中没有看到两个以上的文件,所以我猜垃圾收集正在清理它,就像你说的那样.【参考方案2】:

不,您不应该在应用程序运行时释放证书对象,因为当请求时,IdentityServer 将尝试使用已释放的证书对象并且会失败。

【讨论】:

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

以上是关于我应该处理 X509Certificate2 吗?的主要内容,如果未能解决你的问题,请参考以下文章

我应该处理 WSASend() 可能不会发送所有数据的事实吗?

REST API 的验收测试 - 我应该处理所有情况吗?

在我使用完服务后,我应该处理服务(层)类吗?

第二次创建peerconeection WebRTC时出现问题(轨道已经存在一个发件人。),我应该处理任何想法

带有 cer 文件的 X509Certificate2 ctor

.NET 中的 X509Certificate2 和 X509Certificate 有啥区别?