2015-12-31 7 views
5

ich im Internet nur Weg gefunden, alle von den iis um die Zertifikate zu bekommen, und ich tue es wie folgt aus (C#):Anfahrt Zertifikat von spezifischen Bindung C#

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

Jetzt versuche ich, eine zu bekommen spezifisches Zertifikat der spezifischen Bindung, wie kann ich es in C# tun?

Antwort

6

Die Zertifikate selbst keine Informationen über die Bindungen halten absolut in IIS verwendet, so dass Sie nicht die Zertifikate aus der Maschine abrufen können und erwarten, dass sie etwas zu IIS bezogen haben. Sie müssten diese Informationen von IIS abfragen.

Dazu müssen Sie einen Verweis auf die Bibliothek hinzufügen, die unter %windir%\system32\inetsrv\Microsoft.Web.Administration.dll zu finden ist (Hinweis: IIS 7 oder neuer muss installiert sein). Danach können Sie etwas wie folgt tun, um das Zertifikat zu erhalten:

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(); 
} 
+0

Das NuGet-Paket ist nicht Microsoft offiziell und sollte vermieden werden. –

+0

Dieses Feld kann für jeden Benutzer festgelegt werden. Überprüfen Sie den Herausgeber und Sie werden sehen. Diese Assembly sollte immer aus dem IIS-Installationsordner hinzugefügt werden. –

+1

Der vollständige Pfad lautet '% windir% \ system32 \ inetsrv \ Microsoft.Web.Administration.dll'. Benutze das bitte. –

4

Ich denke, Camilo's Antwort hat ein kleines Problem. Soweit ich das sehe (getestet), funktioniert der Code, um das Zertifikat zu finden, nicht, weil System.Convert.ToBase64String(binding.CertificateHash) keinen gültigen Zertifikat-Fingerabdruck zurückgibt.

Meine Version:

/// <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 
    } 

Diese Funktion funktioniert auch, wenn mehrere https-Sites auf demselben Server gehostet werden (getestet) und sollte funktionieren, wenn die Site einen anderen Port als 443 (nicht getestet) verwendet. Um verbindliche Informationen zu erhalten, wird %windir%\system32\inetsrv\Microsoft.Web.Administration.dll verwendet, wie in Camilos Antwort.

+0

Ich erfahre den gleichen Fehler, und Ihr Code funktioniert perfekt! – Muis