使用WCF时,如何验证证书在其证书链中是否具有特定CA.

时间:2012-07-06 18:48:33

标签: wcf security x509certificate

我要求确保客户端在WCF会话期间提供的x509证书在其链中具有特定的证书颁发机构。

我知道我可以使用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 个答案:

答案 0 :(得分: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>