[原创]x.509证书在WCF中的应用(Web/IIS篇)

简介: 在上一篇"x.509证书在WCF中的应用(CS篇)"里,我们知道了如何在应用程序中,利用x.509证书来验证WCF的消息安全(没看过的朋友建议先看下,地址http://www.cnblogs.com/yjmyzz/archive/2008/08/20/1272550.html),这一篇我们将尝试把x.509证书放到IIS里来验证WCF。

在上一篇"x.509证书在WCF中的应用(CS篇)"里,我们知道了如何在应用程序中,利用x.509证书来验证WCF的消息安全(没看过的朋友建议先看下,地址http://www.cnblogs.com/yjmyzz/archive/2008/08/20/1272550.html),这一篇我们将尝试把x.509证书放到IIS里来验证WCF。

WCF宿主在IIS和普通应用程序里,原理虽然没什么不同,但在实际测试中发现,如果服务端与客户端都采用x.509证书来验证,服务端设置的自定义验证客户端证书的方法总是不起作用,无奈之下,只能在客户端采用了一种变相的方法来验证客户端证书。

废话不多说,还是来看具体步骤吧:

开发环境: Windows2003 + VS2008(SP1)

一.申请/颁发服务端证书和客户端证书
默认情况下,用makecert制作的证书,我经过多次尝试,在IE7里始终被认为不信任的证书(也许是我makecert的参数不对),导致在IE7里测试SSL时,总是显示"证书错误,导航已阻止"之类,所以在本例中,我们换一种方式,用windows2003自带的证书服务来申请/颁发服务端证书和客户端证书,对这一块不熟悉的朋友,请参见"[原创图解]Win2003证书服务配置/客户端(服务端)证书申请/IIS站点SSL设置"一文(地址:http://www.cnblogs.com/yjmyzz/archive/2008/08/21/1273201.html),这里要注意的是服务端证书的"颁发给"的对象一定要和最后运行的url里的计算机名(或域名)信息一致,如下图,否则IE7会认为该证书有问题


二.Wcf web服务端开发
1.vs2008启动后,新建一个web Application(本例命名为WebServer),添加一个wcf服务,命名为MyService,同样系统会自动增加一个IMyService的接口,这二个文件的内容如下:
MyService.svc.cs(代码很简单,返回服务端时间而已)

using  System;
using  System.ServiceModel;

namespace  WebServer
{
    
//  NOTE: If you change the class name "MyService" here, you must also update the reference to "MyService" in Web.config.
     public   class  MyService : IMyService
    {
        
public   string  Test()
        {           
            
return   " 服务端时间:<br/> "   +  DateTime.Now.ToString();
        }
    }
}

IMyService.cs内容
using  System;
using  System.ServiceModel;
using  System.Text;

namespace  WebServer
{
    
//  NOTE: If you change the interface name "IMyService" here, you must also update the reference to "IMyService" in Web.config.
    [ServiceContract]
    
public   interface  IMyService
    {
        [OperationContract]
        
string  Test();
    }
}

配置文件Web.Config关键节点内容如下:
< system.serviceModel >
        
< behaviors >
            
< serviceBehaviors >
                
< behavior name = " WebServer.MyServiceBehavior " >
                    
                    
< serviceMetadata httpGetEnabled = " false "  httpsGetEnabled = " true "  httpsGetUrl = " https://jimmycntvs/MyService.svc " />
                        
< serviceDebug includeExceptionDetailInFaults = " false " />
                    
< serviceCredentials >
                        
<!-- 下面这一行,在测试过程中,发现始终不起作用,只能放弃,转而在客户端的配置中用findValue = " ec0aa48043eab64714c92a0ff7fa0365e1b594af "  x509FindType = " FindByThumbprint "  类似这样的方法来验证指定的客户端证书 -->
                        
<!--< clientCertificate >
                            
< authentication certificateValidationMode = " Custom "  customCertificateValidatorType = " WebServer.CustomX509CertificateValidator,WebServer " />
                        
</ clientCertificate >-->
                        
< serviceCertificate findValue = " JimmyCntvs "  storeLocation = " LocalMachine "   x509FindType = " FindBySubjectName "  storeName = " My " />
                    
</ serviceCredentials >
                    
                
</ behavior >                 
            
</ serviceBehaviors >
        
</ behaviors >
        
< bindings >             
            
< wsHttpBinding >
                
< binding name = " wsHttpBinding_MyService " >
                    
< security mode = " Transport " >
                        
< transport clientCredentialType = " None " />
                        
<!-- 设置成Certificate后,启动WCF时,总是提示出错[ 服务“SslRequireCert”的 SSL 设置与 IIS“Ssl”的 SSL 设置不匹配。]无奈只能设置成None -->
                        
<!--< transport clientCredentialType = " Certificate " />-->
                        
< message clientCredentialType = " Certificate " />                                                           
                    
</ security >                    
                
</ binding >
            
</ wsHttpBinding >
        
</ bindings >
        
< services >
           
< service behaviorConfiguration = " WebServer.MyServiceBehavior "
            name
= " WebServer.MyService " >
               
< endpoint address = " https://jimmycntvs/MyService.svc "  binding = " wsHttpBinding "
                bindingConfiguration
= " wsHttpBinding_MyService "  contract = " WebServer.IMyService "   >
                   
< identity >
                       
< dns value = " jimmycntvs " />
                   
</ identity >
               
</ endpoint >            
           
</ service >
  
</ services >
    
</ system.serviceModel >
 解释一下:
 <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" httpsGetUrl=" https://jimmycntvs/MyService.svc%22/>这行表明,只能用https方式取得wcf的元数据,httpsGetUrl标明了取得WCF元数据的地址
 
 
 <serviceCertificate findValue="JimmyCntvs" storeLocation="LocalMachine"  x509FindType="FindBySubjectName" storeName="My"/>这一句指wcf服务启动时,先验证服务端是否在LocalMachine这个位置有一个SubjectName为JimmyCntvs的服务端证书
 
 <security mode="Transport">
      <transport clientCredentialType="None"/>                      
      <message clientCredentialType="Certificate"/>                                                         
  </security> 这里表示用Transport模式来进行安全验证,详细安全参数含义可参见 http://www.cnblogs.com/yjmyzz/archive/2008/08/19/1271133.html

2.IIS服务端配置
为方便测试,在IIS中直接把WebServer项目配置为一个站点(本例为http://localhost/),同时正确安装第一步颁发的服务端证书,同时把"要求安全通道(SSL)"选中,这样站点就必须用https://来访问了

这些都弄好以后,就可以测试了,浏览https://localhost/MyService.svc,如果是IE7,可能会报一个"证书错误:导航已阻止"的错误,没关系,把localhost换成计算机名(本例中为jimmycntvs)就正常了,如下图:


三.Web 客户端开发
1.先生成服务端WCF的代理
vs2008命令行下运行
svcutil.exe https://jimmycntvs/MyService.svc?wsdl /d:c:\123 即把代理文件和配置文件输出到c:\123下

2.安装客户端证书
把第一步颁发的客户端证书正确安装,同时查看该证书的详细信息,记下"微缩图"去掉空格后的值(本例为ec0aa48043eab64714c92a0ff7fa0365e1b594af,每个证书的这个值都是唯一的),后面会用到


3.vs.net2008新建一个WebClient的webApplication,把刚才的这二个文件加到WebClient中,同时output.config改名为Web.config,关键节点调整如下:

< system.serviceModel >
        
< behaviors >
            
< endpointBehaviors >
                
< behavior name = " NewBehavior " >
                    
< clientCredentials >
                        
<!--< clientCertificate findValue = " Jimmy.Yang "  x509FindType = " FindBySubjectName "  storeLocation = " CurrentUser "  storeName = " My " />-->
                        
<!-- 由于服务端设置的 < authentication certificateValidationMode = " Custom "  customCertificateValidatorType = " WebServer.CustomX509CertificateValidator,WebServer " /> 在测试中发现总是不起作用,所以只能转而用下面的方式从客户端来验证特定的证书,理论上讲这样有安全隐患,建议实际操作时,可将本节加密后,再连同客户端证书一起分发给客户端,若用于安全性较高的环境,建议还是用UserName方式,到数据库里验证用户名和密码 -->
                        
< clientCertificate findValue = " ec0aa48043eab64714c92a0ff7fa0365e1b594af "  x509FindType = " FindByThumbprint "  storeLocation = " CurrentUser "  storeName = " My " />                          < serviceCertificate >
                            
< authentication certificateValidationMode = " None "   />
                        
</ serviceCertificate >
                    
</ clientCredentials >
                
</ behavior >
            
</ endpointBehaviors >
        
</ behaviors >
        
< bindings >
            
< wsHttpBinding >
                
< binding name = " WSHttpBinding_IMyService "  closeTimeout = " 00:01:00 "
                    openTimeout
= " 00:01:00 "  receiveTimeout = " 00:10:00 "  sendTimeout = " 00:01:00 "
                    bypassProxyOnLocal
= " false "  transactionFlow = " false "  hostNameComparisonMode = " StrongWildcard "
                    maxBufferPoolSize
= " 524288 "  maxReceivedMessageSize = " 65536 "
                    messageEncoding
= " Text "  textEncoding = " utf-8 "  useDefaultWebProxy = " true "
                    allowCookies
= " false " >
                    
< 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 "  proxyCredentialType = " None "
                            realm
= ""   />
                        
< message clientCredentialType = " Certificate "  negotiateServiceCredential = " true "
                            establishSecurityContext
= " true "   />
                    
</ security >
                
</ binding >
            
</ wsHttpBinding >
        
</ bindings >
        
< client >
            
< endpoint address = " https://jimmycntvs/MyService.svc "  binding = " wsHttpBinding "
                bindingConfiguration
= " WSHttpBinding_IMyService "  contract = " IMyService "
                name
= " WSHttpBinding_IMyService "  behaviorConfiguration = " NewBehavior " >
                
< identity >
                    
< dns value = " jimmycntvs "   />
                
</ identity >
            
</ endpoint >
        
</ client >
    
</ system.serviceModel >
主要是增加了behaviors这一节,用于查询客户端机器是否有微缩图为ec0aa48043eab64714c92a0ff7fa0365e1b594af的证书
<behaviors>
            <endpointBehaviors>
                <behavior name="NewBehavior">
                    <clientCredentials>                        
                        <clientCertificate findValue="ec0aa48043eab64714c92a0ff7fa0365e1b594af" x509FindType="FindByThumbprint" storeLocation="CurrentUser" storeName="My"/>                        <serviceCertificate>
                            <authentication certificateValidationMode="None" />
                        </serviceCertificate>
                    </clientCredentials>
                </behavior>
            </endpointBehaviors>
        </behaviors>     
       
最后,我们在Default.aspx.cs中加几行代码,用来调用WebServer中的WCF
protected   void  Page_Load( object  sender, EventArgs e)
{
    
using  (MyServiceClient _client  =   new  MyServiceClient()) 
    {
        
string  _test  =  _client.Test();
        Response.Write(_test);
    }
}

运行一下,正常的话,应该会返回服务端的时间。 欢迎转载,转载请注明来自cnblogs"菩提树下的杨过"

编后语:
本文演示了如何将WCF Host在IIS中,并对服务端和客户端都采用x.509证书方式来验证,当然这种方式要求每个客户端机器上都必须安装服务端颁发的证书。在互联网环境下,这可能会给客户端的使用带来麻烦,这时可以采用服务端用x.509方式验证,客户端用经典的用户名/密码的方式来验证,详情可参见http://www.cnblogs.com/fineboy/archive/2008/03/26/1122650.html,写得很详细,一看就知.

目录
相关文章
|
9天前
|
前端开发 JavaScript 关系型数据库
从前端到后端:构建现代化Web应用的技术探索
在当今互联网时代,Web应用的开发已成为了各行各业不可或缺的一部分。从前端到后端,这篇文章将带你深入探索如何构建现代化的Web应用。我们将介绍多种技术,包括前端开发、后端开发以及各种编程语言(如Java、Python、C、PHP、Go)和数据库,帮助你了解如何利用这些技术构建出高效、安全和可扩展的Web应用。
|
25天前
|
监控 Serverless 测试技术
Serverless 应用引擎常见问题之做的web服务计费如何解决
Serverless 应用引擎(Serverless Application Engine, SAE)是一种完全托管的应用平台,它允许开发者无需管理服务器即可构建和部署应用。以下是Serverless 应用引擎使用过程中的一些常见问题及其答案的汇总:
327 3
|
2天前
|
缓存 负载均衡 数据库
优化后端性能:提升Web应用响应速度的关键策略
在当今数字化时代,Web应用的性能对于用户体验至关重要。本文探讨了如何通过优化后端架构和技术手段,提升Web应用的响应速度。从数据库优化、缓存机制到异步处理等多个方面进行了深入分析,并提出了一系列实用的优化策略,以帮助开发者更好地应对日益增长的用户访问量和复杂的业务需求。
8 1
|
2天前
|
缓存 监控 数据库
Flask性能优化:打造高性能Web应用
【4月更文挑战第16天】本文介绍了提升Flask应用性能的七大策略:优化代码逻辑,减少数据库查询,使用WSGI服务器(如Gunicorn、uWSGI),启用缓存(如Flask-Caching),优化数据库操作,采用异步处理与并发(如Celery、Sanic),以及持续监控与调优。通过这些手段,开发者能有效优化Flask应用,适应大型或高并发场景,打造高性能的Web服务。
|
3天前
|
数据库 开发者 Python
Python中使用Flask构建简单Web应用的例子
【4月更文挑战第15天】Flask是一个轻量级的Python Web框架,它允许开发者快速搭建Web应用,同时保持代码的简洁和清晰。下面,我们将通过一个简单的例子来展示如何在Python中使用Flask创建一个基本的Web应用。
|
7天前
|
JavaScript 前端开发 API
Vue.js:构建高效且灵活的Web应用的利器
Vue.js:构建高效且灵活的Web应用的利器
|
15天前
|
XML JSON JavaScript
使用JSON和XML:数据交换格式在Java Web开发中的应用
【4月更文挑战第3天】本文比较了JSON和XML在Java Web开发中的应用。JSON是一种轻量级、易读的数据交换格式,适合快速解析和节省空间,常用于API和Web服务。XML则提供更强的灵活性和数据描述能力,适合复杂数据结构。Java有Jackson和Gson等库处理JSON,JAXB和DOM/SAX处理XML。选择格式需根据应用场景和需求。
|
30天前
|
前端开发 JavaScript 安全
深入探索 Qt6 web模块 WebEngineCore:从基础原理到高级应用与技巧
深入探索 Qt6 web模块 WebEngineCore:从基础原理到高级应用与技巧
71 0
|
30天前
|
缓存 监控 应用服务中间件
如何使用负载均衡器提升Python Web应用的性能?
【2月更文挑战第27天】【2月更文挑战第94篇】如何使用负载均衡器提升Python Web应用的性能?
|
1月前
|
物联网 调度 开发者
构建高效Python Web应用:异步编程与Tornado框架解析
【2月更文挑战第27天】 在处理高并发的Web应用场景时,传统的同步阻塞模型往往难以满足性能需求。本文将深入探讨Python世界中的异步编程概念,并结合Tornado这一轻量级、非阻塞式Web服务器及框架,展示如何构建高性能的Web应用。通过实例驱动的方法论,我们将剖析Tornado的核心组件,包括其IOLoop、异步HTTP客户端和服务器端处理机制,以及与协程集成的细节。文章旨在为开发者提供一套实践指南,帮助他们利用Python实现快速响应和资源高效的Web服务。
28 2