当前位置:编程学习 > 网站相关 >>

[WCF安全系列]实例演示:TLS/SSL在WCF中的应用[HTTPS]

上一篇演示的是绑定类型为NetTcpBinding情况下基于TLS/SSL的Transport安全模式的实现,接下来我们改用另外一种绑定:WS2007HttpBinding。对于基于HTTP的绑定,Transport安全模式的实现方式又根据寄宿方式的不同而具有一定的差异,我们首先来介绍自我寄宿的方式。

一、自我寄宿(Self-Hosting)
无论对于HTTPS还是SSL Via TCP,服务端都需要绑定一个证书。对于采用后者的NetTcpBinding,我们是通过ServiceCredentials这个服务行为来进行证书设置的。但是对于HTTPS,我们需要通过相应的命令行工具将一个X.509证书绑定到相应的端口。而这个工具的选择依赖于机器的操作系统,对于Windows XP和Windows 2003,该命令行工具为httpcfg.exe,而对应之后的版本,则是netsh.exe。关于如何通过httpcfg.exe和netsh.exe为端口设置SSL证书,你可以参考:http://msdn.microsoft.com/zh-cn/library/ms733791.aspx。

httpcfg.exe和netsh.exe均是通过证书的指纹(thumbprint)来关联具体的证书的,在这里具有全局唯一特性的指纹可以看成是证书的唯一标识。我们之前已经通过MakeCert命令行创建了一个主题为Jinnan-PC的证书,我们现在重用该证书。你可以通过MMC的证书管理单元来查看证书的指纹,并将其拷贝到写字板上(比如指纹为:‎f332bf17db3abb8f9a9a2694ba2c75da701bef0f),然后根据操作系统的不同分别执行httpcfg.exe和netsh.exe命令行,为端口3721进行SSL证书的设置,你可以将任意有效的GUID作为appid的参数。

httpcfg set ssl -i 0.0.0.0:3721 -h f332bf17db3abb8f9a9a2694ba2c75da701bef0fORnetsh http add sslcert ipport=0.0.0.0:3721 certhash= f332bf17db3abb8f9a9a2694ba2c75da701bef0f  appid={CFA5621F-CD55-4009-AD7E-51EDDAEC5786}
接下来我们将服务寄宿配置替换成如下的形式。从配置中我们可以看出,寄宿服务的唯一终结点采用了被设置成Transport模式,客户端凭证类型为None的WS2007HttpBinding。地址被设置成https://Jinan-PC:3721/calculatorservice,3721正式上面我们进行SSL证书设置的端口。

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<system.serviceModel>

  <bindings>   

 <ws2007HttpBinding>     

<binding name="transportWS2007HttpBinding">       

 <security mode="Transport">         

<transport clientCredentialType="None"/>       

</security>    

  </binding>   

 </ws2007HttpBinding>       

</bindings> 

<services>  

  <service name="Artech.WcfServices.Services.CalculatorService">     

<endpoint address="https://Jinnan-PC:3721/calculatorservice" binding="ws2007HttpBinding" bindingConfiguration="transportWS2007HttpBinding" contract="Artech.WcfServices.Contracts.ICalculator" />    </service> 

 </services> 

</system.serviceModel>

</configuration>
客户端的配置和编程同样进行相应的修改,具有与服务端相同的绑定设置。具体的配置和服务调用程序如下所示。

<?xml version="1.0" encoding="utf-8" ?>

<configuration> 

<system.serviceModel>   

 <bindings>     

 <ws2007HttpBinding>       

 <binding name="transportWS2007HttpBinding">         

<security mode="Transport">           

<transport clientCredentialType="None"/>        

  </security>       

 </binding>    

  </ws2007HttpBinding>   

</bindings>  

  <client>     

<endpoint name="calculatorService" address="https://Jinnan-PC:3721/calculatorservice" binding="ws2007HttpBinding" bindingConfiguration="transportWS2007HttpBinding" contract="Artech.WcfServices.Contracts.ICalculator" />    </client> 

</system.serviceModel>

</configuration>
服务调用程序:

using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorService"))

{  

  ICalculator calculator = channelFactory.CreateChannel();   

 Console.WriteLine("x + y = {2} when x = {0} and y = {1}", 1, 2, calculator.Add(1, 2)); ;

}
然后我们运行程序,你会发现如下图所示的SecurityNegotiationException异常在服务调用过程中被抛出,并提示“无法为SSL/TLS 安全通道与颁发机构“jinnan-pc:3721”建立信任关系”。抛出异常的原因和之前一致:证书不受信任,因为HTTPS在默认的情况下依然采用ChainTrust认证模式。

 

如果证书是官方机构颁发,你可以将CA证书导入到“受信任根证书颁发机构”存储区来解决这个问题。但是由于对于我们这个测试程序来说,你需要需求另外的办法,也就是改变客户端对SSL证书的认证方式。不过这与采用NetTcpBinding时通过终结点行为ClientCredentials来设置服务证书认证模式的方式有所不同,这里需要采用另外一种方式。你需要通过注册ServicePointManager静态ServerCertificateValidationCallback回调自定义证书认证方式,ServerCertificateValidationCallback回调在ServicePointManager中的定义如下面的代码片断所示。

   1: public class ServicePointManager   2: {   3:     //其他成员   4:     public static RemoteCertificateValidationCallback ServerCertificateValidationCallback { get; set; }   5: }   6: public delegate bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate,    7: X509Chain chain, SslPolicyErrors sslPolicyErrors);
在下面给出的代码片断中,我通过在进行服务调用之前通过注册ServerCertificateValidationCallback回调的方式来忽略掉对SSL证书的认证,就可以抑制SecurityNegotiationException异常的抛出。

   1: ServicePointManager.ServerCertificateValidationCallback+=( sender,  certificate,  chain,  sslPolicyErrors)=>true;  

2: using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorService"))  

3: {  

4:     ICalculator calculator = channelFactory.CreateChannel();  

5:     Console.WriteLine("x + y = {2} when x = {0} and y = {1}", 1, 2, calculator.Add(1, 2)); ;  

6: }
对于SSL证书的认证,还有一点需要说明的是:在默认的情况下,客户端除了采用ChainTrust模式对证书进行认证之外,还具有一个认证规则,那就是要求终结点地址的DNS和证书的主体名称相匹配。以我们创建的这个程序为例,如果我们将客户端配置文件中的终结点地址从https://Jinnan-PC:3721/calculatorservice替换成https://localhost:3721/calculatorservice,在进行服务调用的时候会抛出SecurityNegotiationException异常。

二、IIS寄宿
最后我们来演示IIS寄宿方式。如果你的IIS中没有一个SSL站点,你需要手工创建。所有先来演示一样如何在你的IIS中创建一个SSL站点,这里以IIS 7.5为例。

当你开启了IIS管理器之后,点击左侧边栏的“应用程序池(Application Pool)”结点,打开应用程序池列表界面。然后通过右击弹出上下文菜单,并选择“添加应用程序池(Add Application Pool)”菜单项,打开添加应用程序池对话框。设置添加的应用程序池的名称(比如“DefaultSSLAppPool”),选择.NET版本(.NET Framework 4.0.30319)和托管管道模式(Integrated)。点击确认后,新的应用程序池被创建

补充:综合编程 , 安全编程 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,