4

我需要确保客户端在 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 频道才能完成此操作?甚至可能吗?

4

1 回答 1

1

这可以通过 WCF 的可扩展性(Introduction to Extensbility)来实现。

举一个具体的例子(如何:创建使用自定义证书验证器的服务

使用该信息和我从StackoverFlow 帖子中收集的信息,我创建了一个服务来检查证书的有效性,并验证它是否来自特定的证书颁发机构。

代码:

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");
      }
    }
  }

网络配置

<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>
于 2012-07-11T20:24:37.060 回答