如何利用Certificate来进行安全的WCF service编程

摘要:

WCF的安全验证模式有很多种,利用certificate进行验证就是一种常见的手段。本文将介绍如何WCF service 服务器端和WCF client客户端同时安装证书,互相进行验证的情景。

假设:我们已经有两个证书,分别用于WCF服务器端(名为:ServerCerficate)和WCF客户端(名为:ClientCertifate)

问题:如何创建证书?

      如果为测试只用,我们可用Microsoft SDK快速创建一个certificate,该command为:makecert.exe

eg. makecert -r -pe -n "CN=WCFServer" -ss My -sky exchange 创建用于服务器端名为WCFServer的证书

eg. makecert -r -pe -n "CN=WCFClient" -ss My -sky exchange 创建用于客户端名为WCFClient的证书

或者到Certificate Authority申请证书。关于如何通过CA申请Certificate,请参考其他Article.

 

正文:

服务器端代码及配置:

1 首先创建一个简单的WCF Service,由于本文重点是如何配置Certificate,故WCF Service非常简单。

如下:

Contract定义:

  [ServiceContract(Namespace = " Intern " )]
    
public   interface  IMyMath
    {
        [OperationContract]
        
int  Sum( int  x,  int  y);
    }

 ServiceType定义:

 [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
   
public   class  MyMath:IMyMath
    {
        
public  MyMath()
        {
            Console.WriteLine(
" MyMath constructor is called " );
        }
        
public   int  Sum( int  x,  int  y)
        {
            
return  x  +  y;
        }
    }

下面利用ServiceHost来承载WCF Service, 代码如下:

 

class  Program
    {
        
static   void  Main( string [] args)
        {
            Type serviceType 
=   typeof (MyMath);
            ServiceHost host 
=   new  ServiceHost(serviceType);
            host.Open();
            Console.WriteLine(
" The Service is listenning " );
            Console.WriteLine(
" Press  to exit " );
            Console.ReadLine();
            host.Close();
           
        }
    }

 最为关键的是,下面定义一个App.config来对WCF Service的发布。
(创建App.config的方法 :New Item -> app.config -> open with -->选择 svcconfigeditor.exe ,然后开始利用该工具进行编辑)

编辑后的App.config如下:

 

xml version = " 1.0 "  encoding = " utf-8 "   ?>
< configuration >
    
< system.serviceModel >
        
< behaviors >
            
< serviceBehaviors >
                
< behavior name = " NewBehavior " >
                    
< serviceCredentials >
                        
< clientCertificate >
                            
< authentication customCertificateValidatorType = " CertificateWCFService.CustomX509CertificatesValidator,CertificateWCFService "
                                certificateValidationMode
= " Custom "   />
                        
clientCertificate >
                        
< serviceCertificate findValue = " MyServer "  storeLocation = " CurrentUser "
                            x509FindType
= " FindBySubjectName "   />
                    
serviceCredentials >
                    
< serviceMetadata httpGetEnabled = " true "   />
                
behavior >
            
serviceBehaviors >
        
behaviors >
        
< bindings >
            
< netTcpBinding >
                
< binding name = " CertificateBinding " >
                    
< security >
                        
< transport clientCredentialType = " Certificate "   />
                    
security >
                
binding >
            
netTcpBinding >
        
bindings >
        
< services >
            
< service behaviorConfiguration = " NewBehavior "  name = " CertificateWCFService.MyMath " >
                
< endpoint address = " MyMath "  binding = " netTcpBinding "  bindingConfiguration = " CertificateBinding "
                    name
= " Test "  contract = " CertificateWCFService.IMyMath "   />
                
< host >
                    
< baseAddresses >
                        
< add baseAddress = " net.tcp://localhost:8010/service "   />
                        
< add baseAddress = " http://localhost:8011/service "   />
                    
baseAddresses >
                
host >
            
service >
        
services >
    
system.serviceModel >
configuration >

需要说明的是,在进行配置的时候 最为关键的是的配置,主要包括的配置,

下面对设置作简单介绍:

在服务器端的serviceBehavior,主要用于指定服务器端的certificate. 而clientCertificate用于指定当接受到客户端的证书时,服务器端对客户端的验证行为,比如此时我们可以自定义一个对客户端的证书验证行为,该自定义的验证行为类必须继承自:

System.IdentityModel.Selectors.X509CertificateValidator,并且重写其 void Validate(X509Certificate2 certificate) 方法

如下图所示:

如何利用Certificate来进行安全的WCF service编程_第1张图片 

ServiceCertificate的配置

图中FindValue即为安装在服务器端的Certificate ,名为MyServer,该Certificate保存在CurrentUser\My下。

如何利用Certificate来进行安全的WCF service编程_第2张图片

比如在上图中,我们对客户端采用的自定义的证书验证,因此其clientCertificateValidationMode设置为custom,同时我们自定义验证类。

代码如下所示:

public   class  CustomX509CertificatesValidator : System.IdentityModel.Selectors.X509CertificateValidator
    {
        
public   override   void  Validate(X509Certificate2 certificate)
        {
            
try
            {
                Console.WriteLine(certificate.Thumbprint);
            }
            
catch  (Exception ex)
            {
                Console.WriteLine(ex.Message.ToString());
            }
        }
    }

当然,这个自定义的验证类只是为了测试自用。其效果为:当WCF客户端请求WCF Service时候,Server接受到来自客户端的Request,Server然后验证来自客户端的certificate.此时服务器端自定义的certificate验证器将会运行,从而在服务器端显示出client Certificate的消息摘要。

比如,WCF Client请求时(说明:WCF client客户端代码将在下面给出),服务器端的运行screenshot如下所示:

如何利用Certificate来进行安全的WCF service编程_第3张图片

红色区域即为客户端的certificate 的消息摘要。客户端证书消息摘要如下所示:

如何利用Certificate来进行安全的WCF service编程_第4张图片

可以看到客户端证书的消息摘要被正确的显示在服务器端的验证器中. 

说明:通过以上配置,我们已经在服务器端配制好了serviceCertificate和对客户端certificate证书的验证行为。但是以上所做的一切,要work的前提条件是我们在自定义bindingConfiguration时候,必须将MessageClientCredentialType或者TransportClientCredentialType设置为Certificate(如果采用传输安全模式,则为TransportClientCredentialType;如采用MessageClientCredentialType,则为MessageClientCredentialType)。否则以上所有设置都是徒劳,因为缺省的凭证类型是windows credential而非certificate. 设置画面如下图所示:

如何利用Certificate来进行安全的WCF service编程_第5张图片

 

客户端代码及配置

在WCF Service正确通过host 承载之后,可以同svcutil command从WCF service的httpMetaURL中获得其相应的代理类 。eg svcutil.exe http://localhost:8081/service /out:MyMathProxy.cs /confit:app.config, 则会在客户端自动生成MyMathProxy.cs和App.config,将其加入到WCF 客户端工程中。

注意:

通过svcutil 生成的App.config不能完全胜任需求,我们还需要对其进行简单改写。方法还是通过svcconfigeditor.exe进行编辑。主要需要改写的地方是要指定 --〉中的

其中:主要指定客户端的certificate

主要指定当服务器端证书到达客户端时,客户端如何对证书进行验证的行为

客户端的App.config如下: 

xml version = " 1.0 "  encoding = " utf-8 " ?>
< configuration >
    
< system.serviceModel >
        
< behaviors >
            
<endpointBehaviors >
                
< behavior name = " NewBehavior " >
                    
<clientCredentials>
                        
<clientCertificate findValue="WCFClient" x509FindType="FindBySubjectName" />
                        
<serviceCertificate>
                            
<authentication customCertificateValidatorType="CertificateClient.CustomCertificateValidator,CertificateClient"
                                certificateValidationMode
="Custom" />
                        
serviceCertificate>
                     clientCredentials >
                
behavior >
            
endpointBehaviors >
        
behaviors >
        
< bindings >
            
< netTcpBinding >
                
< binding name = " Test "  closeTimeout = " 00:01:00 "  openTimeout = " 00:01:00 "
                    receiveTimeout
= " 00:10:00 "  sendTimeout = " 00:01:00 "  transactionFlow = " false "
                    transferMode
= " Buffered "  transactionProtocol = " OleTransactions "
                    hostNameComparisonMode
= " StrongWildcard "  listenBacklog = " 10 "
                    maxBufferPoolSize
= " 524288 "  maxBufferSize = " 65536 "  maxConnections = " 10 "
                    maxReceivedMessageSize
= " 65536 " >
                    
< readerQuotas maxDepth = " 32 "  maxStringContentLength = " 8192 "  maxArrayLength = " 16384 "
                        maxBytesPerRead
= " 4096 "  maxNameTableCharCount = " 16384 "   />
                    
< reliableSession ordered = " true "  inactivityTimeout = " 00:10:00 "
                        enabled
= " false "   />
                    
< security mode = " Transport " >
                        
< transport clientCredentialType = " Certificate "  protectionLevel = " EncryptAndSign "   />
                        
< message clientCredentialType = " Windows "   />
                    
security >
                
binding >
            
netTcpBinding >
        
bindings >
        
< client >
            
< endpoint address = " net.tcp://localhost:8010/service/MyMath "  behaviorConfiguration = " NewBehavior "
                binding
= " netTcpBinding "  bindingConfiguration = " Test "  contract = " IMyMath "
                name
= " Test " >
                
< identity >
                    
< dns value = " MyServer "   />
                
identity >
            
endpoint >
        
client >
    
system.serviceModel >
configuration >

 

而客户端的自定义证书验证器如下所示: 

  public   class  CustomCertificateValidator : System.IdentityModel.Selectors.X509CertificateValidator
    {
        
public   override   void  Validate(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate)
        {
            Console.WriteLine(certificate.Subject);
            Console.WriteLine(certificate.Thumbprint);
        }
    }

 

WCF client如下所示:

class  Program
    {
        
static   void  Main( string [] args)
        {
            MyMathClient proxy 
=   new  MyMathClient();
           
//  proxy.Open();
            
// int result=proxy.Sum(3, 4);
            Console.WriteLine( " sum(3,4) is {0} " , proxy.Sum( 3 , 4 ));
            Console.WriteLine(
" sum(3,4) is {0} " , proxy.Sum( 3 4 ));
           
//  proxy.Close();
            Console.ReadLine();
        }
    }

客户端运行screenshot如下所示:

如何利用Certificate来进行安全的WCF service编程_第6张图片

可以看到WCF Client已经验证了WCF Server端的Certificate

如何利用Certificate来进行安全的WCF service编程_第7张图片

转载于:https://www.cnblogs.com/Winston/archive/2008/10/28/1321543.html

你可能感兴趣的:(如何利用Certificate来进行安全的WCF service编程)