2012-07-06 53 views
4

我有一個要求,以確保客戶端在WCF會話期間呈現的x509證書在其鏈中具有特定的證書頒發機構。如何驗證證書在其證書鏈中具有特定的CA時使用WCF

我知道我可以使用ChainElements [index]以編程方式檢查證書鏈。

但我不確定如何做到這一點,同時仍然使用配置文件與WCF集成。

目前WCF是建立在一個配置文件,見下圖:

<services> 
    <service name="SampleService" behaviorConfiguration="wsHttpBehavior"> 
    <endpoint name="SampleEndPoint" 
       address="http://localhost:70000/SampleService.svc" 
       binding="wsHttpBinding" 
       bindingConfiguration="wsHttpBinding" 
       contract="SampleApp.ISampleService"> 
    </endpoint> 
    </service> 
</services> 

<bindings> 
    <wsHttpBinding> 
    <binding name="wsHttpBinding"> 
     <reliableSession enabled="true" ordered="true" /> 
     <security> 
     <message clientCredentialType="Certificate" /> 
     </security> 
    </binding> 
    </wsHittpBinding> 
</bindings> 

<behaviors> 
    <serviceBehaviors> 
    <serviceMetadata httpGetEnabled="true" /> 
    <serviceDebug includeExceptionDetailInFaults="false" /> 
    <serviceCredentials> 
     <serviceCertificate findValue="aa aa aa" 
          storeLocation="LocalMachine" 
          storeName="My" 
          x509FindType="FindBySerialNumber" /> 
    </serviceCredentials> 
    <serviceBehaviors> 
</behaviors> 

有什麼,我可以在配置文件中做的告訴它,以確保這是所提供的客戶端證書包含一個特定的認證機構。或者我必須綁定到WCF頻道才能完成此操作?它甚至有可能嗎?

回答

1

這可以通過WCF的擴展性(Introduction to Extensbility)來完成。

對於具體的示例(How to: Createa Service that Employs a Custom Certificate Validator

使用該信息,而且我從this StackoverFlow post收集我創建了一個檢查證書的有效性,以及驗證它從一個特定的證書頒發機構傳來的服務信息。

代碼:

public class CustomX509CertificateValidator : X509CertificateValidator 
    { 
    public override void Validate(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) 
    { 
     var ch = new X509Chain(); 

     //RevocationMode Enumeration 
     //http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509revocationmode.aspx 
     ch.ChainPolicy.RevocationMode = X509RevocationMode.Online; 

     //RevocationFlag Enumeration 
     //http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509revocationflag.aspx 
     ch.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; 

     //The time span that elapsed during online revocation verification or downloading the 
     //certificate revocation list (CRL) 
     ch.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(1000); 

     //VerificationFlags Enumeration 
     //http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509verificationflags.aspx 
     ch.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag; 

     //The time that the certificate was verified expressed in local time 
     ch.ChainPolicy.VerificationTime = DateTime.Now; 

     ch.Build(certificate); 

     //Check to see if the CA is a specific one 
     if (ch.ChainElements[ch.ChainElements.Count - 1].Certificate.IssuerName.Name != "CN=Something, OU=PKI...,") 
     { 
     throw new SecurityTokenValidationException("Certificate was not issued by a trusted issuer"); 
     } 

     foreach (X509ChainStatus s in ch.ChainStatus) 
     { 
     string str = s.Status.ToString(); 
     Console.WriteLine("str: " + str); 
     } 

     //Check to see if the current certificate is revoced in the current system (does this not happen in the above? 
     X509Store store = new X509Store(StoreName.Disallowed, StoreLocation.LocalMachine); 
     store.Open(OpenFlags.ReadOnly); 
     bool isRevoked = store.Certificates.Contains(certificate); 
     store.Close(); 

     if (isRevoked) 
     { 
     throw new SecurityTokenValidationException("Certificate is revoked"); 
     } 

     if (certificate.Verify() == false) 
     { 
     throw new SecurityTokenValidationException("Certificate cannot be verified"); 
     } 
    } 
    } 

的web.config

<behaviors> 
    <serviceBehaviors> 
    <behavior name="secureHttpBehavior"> 
     <serviceMetadata httpGetEnabled="true"/> 
     <serviceDebug includeExceptionDetailInFaults="false"/> 
     <serviceCredentials> 
     <serviceCertificate findValue="00 b7 70" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySerialNumber"/> 
     <clientCertificate> 
      <authentication certificateValidationMode="Custom"    
          customCertificateValidatorType="WcfWebServer.CustomX509CertificateValidator, WcfWebServer"/> 
     </clientCertificate> 
     </serviceCredentials> 
    </behavior> 
    </serviceBehaviors> 
</behaviors>