专栏首页大内老A[WCF安全系列]谈谈WCF的客户端认证[X.509证书认证]

[WCF安全系列]谈谈WCF的客户端认证[X.509证书认证]

前面介绍Windows认证用户名/密码认证这两种典型的客户端认证模式,我们最后来介绍最后一种客户端认证方式,即客户端凭证类型为X.509证书时服务端采用的认证,简称为证书认证。我们照例先看看看客户端证书凭证如何设置设置。

一、客户端证书凭证的设置

服务认证一文中,我们知道了基于X.509证书证书的服务凭证通过X509CertificateRecipientServiceCredential类型表示。与之对应地,客户端凭证对应的类型是X509CertificateInitiatorClientCredential。如下面的定义所示,在终结点行为 ClientCredentials中,具有一个只读的ClientCertificate属性,其类型就是X509CertificateInitiatorClientCredential。该类型实际上是对一个X509Certificate2类型对象的封装,我们可以通过两个SetCertificate方法重载以证书引用的方式指定某个具体的X.509证书作为客户端的凭证。

   1: public class ClientCredentials : SecurityCredentialsManager, IEndpointBehavior
   2: {    
   3:     //其他成员
   4:     public X509CertificateInitiatorClientCredential ClientCertificate { get; }
   5: }
   6: public sealed class X509CertificateInitiatorClientCredential
   7: {
   8:     //其他成员
   9:     public void SetCertificate(string subjectName, StoreLocation storeLocation, StoreName storeName);
  10:     public void SetCertificate(StoreLocation storeLocation, StoreName storeName, X509FindType findType, object findValue);
  11:     public X509Certificate2 Certificate { get; set; }
  12: }

在下面给出服务调用代码中,我们通过编程的方式为ChannelFactory<TChannel>设置了一个基于X.509证书的客户端凭证。

   1: using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorService"))
   2: {
   3:     channelFactory.Credentials.ClientCertificate.SetCertificate(
   4:         StoreLocation.LocalMachine, 
   5:         StoreName.TrustedPeople, 
   6:         X509FindType.FindBySubjectName, 
   7:         "‎‎‎Foo");
   8:     ICalculator calculator = channelFactory.CreateChannel();
   9:     double result = calculator.Add(1, 2);
  10:     //...
  11: }

终结点行为ClientCredentials同样为客户端(默认)证书的设置定义相应的配置。在下面给出的XML片断中,我们通过配置的方式为终结点凭证指定了一个X.509证书。这个证书将作为服务代理对象(通过ChannelFactory<TChannel>创建的代理,或者是直接实例化通过元数据导入生成的服务代理类型)的默认客户凭证,而该凭证可以通过编程进行动态更改。

   1: <system.serviceModel>
   2:   ...
   3:   <behaviors>
   4:     <endpointBehaviors>
   5:       <behavior name="defaultClientCert">
   6:         <clientCredentials>
   7:           <clientCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" findValue="Foo"/>
   8:         </clientCredentials>
   9:       </behavior>
  10:     </endpointBehaviors>
  11:   </behaviors>
  12: </system.serviceModel>

二、客户端证书认证模式

关于基于证书的客户端认证,你可以与基于证书的服务认证进行类比。对于服务认证,服务在寄宿的时候指定某个X.509证书作为服务的凭证。客户端在默认的情况下会以ChainTrust模式对服务证书进行认证,也可以通过ClientCredentials这个终结点行为指定不同的认证模式。对于客户端认证,认证方变成了服务本身,服务端对客户证书的认证也采用相同的策略:默认认证模式为ChainTrust,但借助ServiceCredentials这个服务行为来指定不同的认证模式。

下面给出了服务端进行客户端证书认证模式设置对应的相关类型的定义。服务行为ServiceCredentials中具有一个只读的ClientCertificate属性,类型为X509CertificateInitiatorServiceCredential(对应于服务认证中的X509CertificateRecipientClientCredential)。X509CertificateInitiatorServiceCredential定义了只读属性Authentication,其类型为X509ClientCertificateAuthentication(对应于服务认证中的X509ServiceCertificateAuthentication)。和X509ServiceCertificateAuthentication定义类似,你可以通过X509ClientCertificateAuthentication设置不同的认证模式(None、PeerTrust、ChainTrust、PeerOrChainTrust、Custom)。当你选择Custom模式的时候,你需要通过CustomCertificateValidator属性设置一个自定义的X509CertificateValidator。

   1: public class ServiceCredentials : SecurityCredentialsManager, IServiceBehavior
   2: {
   3:     //其他成员
   4:     public X509CertificateInitiatorServiceCredential ClientCertificate { get; }
   5: }
   6: public sealed class X509CertificateInitiatorServiceCredential
   7: {
   8:     //其他成员
   9:     public X509ClientCertificateAuthentication Authentication { get; }
  10:     public X509Certificate2 Certificate { get; set; }
  11: }
  12: public class X509ClientCertificateAuthentication
  13: {
  14:     //其他成员
  15:     public X509CertificateValidationMode CertificateValidationMode { get; set; }
  16:     public X509CertificateValidator CustomCertificateValidator { get; set; }
  17: }

下面的代码演示了在对服务进行自我寄宿的情况下,如何设置对客户端证书进行认证的模式,在这里将认证模式设置成了PeerOrChainTrust。

   1: using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
   2: {
   3:     ServiceCredentials serviceCredentials = host.Description.Behaviors.Find<ServiceCredentials>();
   4:     if (null == serviceCredentials)
   5:     {
   6:         serviceCredentials = new ServiceCredentials();
   7:         host.Description.Behaviors.Add(serviceCredentials);
   8:     }
   9:     serviceCredentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust;
  10:     host.Open();
  11:     //...
  12: }

我们推荐的依旧是采用配置的方式,上面这段代码中设置的服务行为可以通过下面一端配置来表示。

   1: <system.serviceModel>
   2: ...
   3:   <behaviors>
   4:     <serviceBehaviors>
   5:       <behavior name="setCertAuthentication">
   6:         <serviceCredentials>
   7:           <clientCertificate>
   8:             <authentication certificateValidationMode="PeerOrChainTrust"/>
   9:           </clientCertificate>
  10:         </serviceCredentials>
  11:       </behavior>
  12:     </serviceBehaviors>
  13:   </behaviors>
  14: </system.serviceModel>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • [WCF安全系列]服务凭证(Service Credential)与服务身份(Service Identity)

    在采用TLS/SSL实现Transport安全的情况下,客户端对服务证书实施认证。但是在默认情况下,这种认证仅仅是确保服务证书的合法性(通过数字签名确保证书确实...

    蒋金楠
  • [WCF安全系列]实例演示:TLS/SSL在WCF中的应用[SSL over TCP]

    在接下来的系列文章中我们正是讨论关于身份认证的主题。在前面我们已经谈到了,WCF中的认证属于“双向认证”,既包括服务对客户端的认证(以下简称客户端认证),也包括...

    蒋金楠
  • Windows安全认证是如何进行的?[Kerberos篇]

    最近一段时间都在折腾安全(Security)方面的东西,比如Windows认证、非对称加密、数字证书、数字签名、TLS/SSL、WS-Security等。如果时...

    蒋金楠
  • 可变大小消息流码中的在线与离线速率对比分析(CS IT)

    为实时通信提供高服务质量是一个普遍存在的挑战,它受到传输过程中数据包丢失的困扰。流码是一类专门为这种低延迟流通信环境设计的擦除码。我们考虑最近提出的可变大小消息...

    刘持诚
  • EMQX MQTT 服务器(下篇)| 开启客户端身份安全认证并使用mqtt.fx测试

    经过实际测试,EMQ X 版本高于 3.0.1 版本无法配置使用插件,所以在进行本节实验之前,先删除原有的 EMQ-X,下载安装 3.0.1 版本。

    Mculover666
  • 视频中的运动特征--Learning Motion Patterns in Videos

    Learning Motion Patterns in Videos CVPR2017 Torch code: http://thoth.inria...

    用户1148525
  • C# on Visual Studio Code

    绿巨人
  • 聊聊claudb的keys command

    claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/key/KeysCommand.ja...

    codecraft
  • 聊聊claudb的keys command

    claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/key/KeysCommand.ja...

    codecraft
  • 消息中间件之RocketMQ简介

    一、什么是RocketMQ ? 上图是一个典型的消息中间件收发消息的模型,RocketMQ也是这样的设计,简单说来,RocketMQ具有以下特点: 是一个队列模...

    lyb-geek

扫码关注云+社区

领取腾讯云代金券