在我的代码中,我枚举了所有本地IIS站点,并为每个站点尝试验证端口443的证书。
using( var sm = new ServerManager() ) {
foreach( var site in sm.Sites ) {
foreach( var binding in site.Bindings ) {
if( binding.EndPoint.Port == 443 ) {
var thumbprint = binding.CertificateHash;
var storeName = binding.CertificateStoreName;
//validation here...
}
}
}
}
此代码表示storeName
为"MY"
而thumbprint
为某些字节数组,我将其转换为十六进制表示。
现在“验证”部分的工作原理如下:
var store = new X509Store("MY");
store.Open(OpenFlags.ReadOnly);
var certs = store.Certificates;
//find and validate my cert
store.Close();
并且此代码产生一个空集合。然而,如果我改变
var store = new X509Store("MY");
到
var store = new X509Store(StoreLocation.LocalMachine);
然后代码产生一个带有两个证书的集合,其中一个具有正确的指纹,我可以验证它。
为什么Binding
会返回证书商店名称,但我在商店中找不到具有该名称的证书?
答案 0 :(得分:3)
商店名称与商店位置之间存在差异。
IIS的所有证书都存储在本地计算机位置,而不是存储在特定用户帐户中。
这就是X509Store
的构造函数,只需要一个StoreLocation
,这是你的第二个例子:
public X509Store(StoreLocation storeLocation) : this("MY", storeLocation)
{
}
调用商店名称和一个位置的constructor。
你的第一个例子:
var store = new X509Store("MY");
打开CurrentUser
的MY
商店,而不是本地机器。所以你正在寻找错误的商店。切换到使用同时包含名称和位置的构造函数。
答案 1 :(得分:0)
此方法将为您获得证书:
private X509Certificate2 GetServiceCertificate(String certificateSubjectName, StoreName storeName = StoreName.My, StoreLocation storeLocation = StoreLocation.CurrentUser)
{
X509Store certificateStore = new X509Store(storeName, storeLocation);
foreach (X509Certificate2 certificate in certificateStore.Certificates)
{
if (certificate.SubjectName.Name == certificateSubjectName)
{
return certificate;
}
}
return null;
}