如何从特定绑定C#

时间:2015-12-31 13:26:18

标签: c# iis ssl binding

我在互联网上找到了从iis获得所有证书的方式,我就像下面这样做了(c#):

var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
store.Certificates;

现在我尝试获取特定绑定的特定证书,如何在C#中完成?

4 个答案:

答案 0 :(得分:6)

证书本身绝对不包含有关IIS中使用的绑定的信息,因此您无法从计算机中检索证书并期望它们具有与IIS相关的任何内容。您需要从IIS查询该信息。

为此,您需要添加对%windir%\system32\inetsrv\Microsoft.Web.Administration.dll下可以找到的库的引用(注意:必须安装IIS 7或更新版本)。在此之后,您可以执行以下操作来获取证书:

ServerManager manager = new ServerManager();
Site yourSite = manager.Sites["yourSiteName"];

X509Certificate2 yourCertificate = null;

foreach (Binding binding in yourSite.Bindings)
{
    if (binding.Protocol == "https" && binding.EndPoint.ToString() == "127.0.0.1" /*your binding IP*/)
    {
        var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        store.Open(OpenFlags.ReadOnly);
        yourCertificate = store.Certificates.Find(X509FindType.FindByThumbprint, ToHex(binding.CertificateHash), true)[0];
        break;
    }
}

public static string ToHex(byte[] ba)
{
    var hex = new StringBuilder(ba.Length * 2);
    foreach (byte b in ba) 
    {
        hex.AppendFormat("{0:x2}", b);
    }

    return hex.ToString();
}

答案 1 :(得分:4)

我认为Camilo的答案有一个小问题。据我所知(测试它),找到证书的代码不起作用,因为System.Convert.ToBase64String(binding.CertificateHash)没有返回有效的证书指纹。

我的版本:

    /// <summary>
    /// Returns the https certificate used for a given local IIS website.
    /// </summary>
    /// <param name="sWebsite">Website url, e.g., "https://myserver.company.com"</param>
    /// <returns>certificate, null if not found</returns>
    private X509Certificate2 FindIisHttpsCert(string sWebsite)
    {
      Uri uriWebsite = new Uri(sWebsite);
      using (ServerManager sm = new ServerManager())
      {
        string sBindingPort = string.Format(":{0}:", uriWebsite.Port);
        Binding bdBestMatch = null;
        foreach (Site s in sm.Sites)
        {
          foreach (Binding bd in s.Bindings)
          {
            if (bd.BindingInformation.IndexOf(sBindingPort) >= 0)
            {
              string sBindingHostInfo = bd.BindingInformation.Substring(bd.BindingInformation.LastIndexOf(':') + 1);
              if (uriWebsite.Host.IndexOf(sBindingHostInfo, StringComparison.InvariantCultureIgnoreCase) == 0)
              {
                if ((bd.Protocol == "https") && ((bdBestMatch == null) || (bdBestMatch.BindingInformation.Length < bd.BindingInformation.Length)))
                  bdBestMatch = bd;
              }
            }
          }
        }
        if (bdBestMatch != null)
        {
          StringBuilder sbThumbPrint = new StringBuilder();
          for (int i = 0; i < bdBestMatch.CertificateHash.Length; i++)
            sbThumbPrint.AppendFormat("{0:X2}", bdBestMatch.CertificateHash[i]);

          X509Store store = new X509Store(bdBestMatch.CertificateStoreName, StoreLocation.LocalMachine);
          store.Open(OpenFlags.ReadOnly);
          X509Certificate2Collection coll = store.Certificates.Find(X509FindType.FindByThumbprint, sbThumbPrint.ToString(), true);
          if (coll.Count > 0)
            return coll[0];
        }
      }
      return null; // if no matching site was found
    }

如果多个https站点托管在同一服务器上(已测试),则此功能也可以正常工作,如果站点使用443以外的端口(未测试),则此功能也可以使用。要获取绑定信息,请使用%windir%\system32\inetsrv\Microsoft.Web.Administration.dll,如Camilo的答案。

答案 2 :(得分:0)

我尝试了解决方案,但是遇到了找不到证书的问题。最终导致需要根据绑定正确指定证书存储:

ServerManager manager = new ServerManager();
Site yourSite = manager.Sites["yourSiteName"];

X509Certificate2 yourCertificate = null;

foreach (Binding binding in yourSite.Bindings)
{
    if (binding.Protocol == "https" && binding.EndPoint.ToString() == "127.0.0.1" /*your binding IP*/)
    {
        var store = new X509Store(binding.CertificateStoreName, StoreLocation.LocalMachine);
        store.Open(OpenFlags.ReadOnly);
        var certs = store.Certificates.Find(X509FindType.FindByThumbprint, ToHex(binding.CertificateHash), true);

        if (certs.Count > 0)
            yourCertificate = certs[0];
        break;
    }
}

public static string ToHex(byte[] ba)
{
    var hex = new StringBuilder(ba.Length * 2);
    foreach (byte b in ba) 
    {
        hex.AppendFormat("{0:x2}", b);
    }

    return hex.ToString();
}

答案 3 :(得分:-1)

以下链接应该有所帮助:

基本上store.Certificates返回特定商店中所有证书的集合,然后您可以搜索所需的那个。如果您知道所需证书的主题名称,该链接将显示如何执行此操作。

How to get X509Certificate from certificate store and generate xml signature data?