[英]Performance impact due to store.Open and store.Certificates.Find methods in X509Store
private static X509Certificate2 FindCertificate(string certificateSubject)
{
const StoreName StoreName = StoreName.My;
const StoreLocation StoreLocation = StoreLocation.LocalMachine;
var store = new X509Store(StoreName, StoreLocation);
try
{
store.Open(OpenFlags.ReadOnly);
// Find with the FindBySubjectName does fetch all the certs partially matching the subject name.
// Hence, further filter for the certs that match the exact subject name.
List<X509Certificate2> clientCertificates =
store.Certificates.Find(X509FindType.FindBySubjectName, certificateSubject, validOnly: true)
.Cast<X509Certificate2>()
.Where(c => string.Equals(
c.Subject.Split(',').First().Trim(),
string.Concat("CN=", certificateSubject).Trim(),
StringComparison.OrdinalIgnoreCase)).ToList();
if (!clientCertificates.Any())
{
throw new InvalidDataException(
string.Format(CultureInfo.InvariantCulture, "Certificate {0} not found in the store {1}.", certificateSubject, StoreLocation.LocalMachine));
}
X509Certificate2 result = null;
foreach (X509Certificate2 cert in clientCertificates)
{
DateTime now = DateTime.Now;
DateTime effectiveDate = DateTime.Parse(cert.GetEffectiveDateString(), CultureInfo.CurrentCulture);
DateTime expirationDate = DateTime.Parse(cert.GetExpirationDateString(), CultureInfo.CurrentCulture);
if (effectiveDate <= now && expirationDate.Subtract(now) >= TimeSpan.FromDays(1))
{
result = cert;
break;
}
}
return result;
}
finally
{
store.Close();
}
}
我的库中有此代码,每次创建新请求时,它都会调用此方法。 所以基本上每秒的请求是1000,那么它将被调用1000次。 当我使用PerfView工具时,我注意到此方法使用了35%的CPU。 最大的罪魁祸首是存储。打开并存储。证书。查找方法。
其他人在他们的代码中发现了类似的问题。 另外,如果您可以分享您为解决此性能影响所做的工作。
只要目标系统未安装大量证书,就可以跳过对X509Store的.Find()
方法的调用。 以我的经验,它的效果不是很好,之后您已经在为目标subjectName
做必要的过滤。
另外,不要循环遍历X509Certificate2
的集合! 如果只希望第一个符合所有条件的匹配证书,则可以将其简化为单个LINQ语句,如下所示:
X509Certificate2 cert =
store.Certificates.Cast<X509Certificate2>()
.FirstOrDefault(xc =>
xc.Subject.Equals("CN=" + certificateSubject, StringComparison.OrdinalIgnoreCase)
&& xc.NotAfter >= DateTime.Now.AddDays(-1)
&& xc.NotBefore <= DateTime.Now);
(请注意,根据您的用法和证书,您可能会或不需要像原始代码一样修改以上内容以逗号分隔主题)。
最后,如Wiktor Zychla所述,如果目标计算机上未安装大量证书,则可以通过调用store.Certificates.Cast<X509Certificate2>().ToList()
来缓存整个证书列表store.Certificates.Cast<X509Certificate2>().ToList()
搜索数量有限的subjectNames
,使用从使用者名称派生的键和基于NotAfter
属性的到期时间来简单地缓存此方法的结果可能会更有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.