重温WCF之WCF传输安全(十三)(4)基于SSL的WCF对客户端采用证书验证(转)
转载地址:http://www.cnblogs.com/lxblog/archive/2012/09/20/2695397.html
前一篇我们演示了基于SSL的WCF 对客户端进行用户名和密码方式的认证,本篇我们演示一下服务器端对客户端采用X.509证书的认证方式是如何实现的。
项目结构及服务代码和前两篇代码是基本一样的,为了大家看着方便,再从头到尾进行一下演示。
一、制作证书:
本次制作证书和第一篇略有不一样,主要为了演示证书的信任链关系,我们首先创建一个证书作为证书认证中心(CA)的根证书,我们还是利用MakeCert命令创建。在“开始”菜单中打开—>Microsoft Visual Studio 2010->Visual Studio 命令提示。
输入:makecert -n "CN=LXCA" -r -sv D:\LXCA.pvk D:\LXCA.cer
这时候会弹出 “创建私钥密码”对话框 和 “输入私钥密码”对话框,我们都输入密码“123456”。(这个密码的作用就是今后对证书进行导入,导出等操作的时候,输入的密码),命令提示成功后,这时候会在我的计算机D盘生成两个文件 LXCA.pvk 和 LXCA.cer。
这里说明一下,证书中三种常用的文件格式:.pvk 文件:私钥文件;.cer 公钥文件;还用一种扩展名为.pfx 文件是包含公钥和私钥的密钥交换文件。
然后我们输入命令:makecert -n "CN=Lx-PC" -ic D:\LXCA.cer -iv D:\LXCA.pvk -sr LocalMachine -ss My -pe -sky exchange
在弹出的 “输入私钥密码” 对话框中输入"123456"之后,提示创建成功。这就是我们的服务器端的证书(至于为什么输入我本机的计算机名CN=Lx-PC,我们前文有讲解),我们可以在运行MMC,在证书管理单元中看到该证书:
我们双击我们创建的这个证书,打开 “详细信息” 标签可以查看到证书的指纹,我们记录下来,我的这个证书的指纹是:f5ccc32b77d5d12922e162a289c80c7e95d615ea
下面和原来一样,将证书与计算机的端口进行绑定,在win7 下,依然使用 netsh 命令(netsh命令位于C:\Windows\System32 下),我们运行该命令,并输入:
http add sslcert ipport=0.0.0.0:9000 certhash=f5ccc32b77d5d12922e162a289c80c7e95d615ea appid={BFC5621F-EF33-4009-AD7E-51EDDAEC4321}
这样我们的证书就和9000端口绑定好了,如何对这两个命令有疑问,请点击这里,对这两个命令和用法有详细的介绍。
到这里,服务器端证书就创建好了,我们还需要将证书的颁发者 LXCA 纳入到 “受信任的根证书颁发结构” 中(这一步主要是为了解决客户端调用的时候产生的信任关系的问题,前文已有介绍)。我们 在MMC 证书管理单元中,在 ”受信任的根证书颁发机构” 节点右击,选择 “所有任务” -->“导入证书”,文件选择D盘的 LXCA.cer 即可,如下图:
之后,我们需要创建两个客户端用到的证书,命令同制作服务器端证书一样:
Makecert -n "CN=Client1-PC" -ic D:\LXCA.cer -iv D:\LXCA.pvk -sr CurrentUser -ss My -pe -sky exchange
Makecert -n "CN=Client2-PC" -ic D:\LXCA.cer -iv D:\LXCA.pvk -sr CurrentUser -ss My -pe -sky exchange
我们创建两个客户端证书Client1-PC 和Client2-PC ,并放到 “当前用户” 的存储区,因为在实际项目中,客户端的证书一般都存储在当前用户下,我们可以在MMC 证书管理单元中看到:
并记录下两个证书的指纹(后面要用到):
Client1-PC 指纹:4df6765861ca5b393127e4aea2d9dffc02ef7346
Client2-PC 指纹:5cd0b75bd54092f022e9c48eb971879dcbdc29c2
二、程序演示
同样看一下项目结构,结构和服务代码和前面几篇用到的一样:
1、 程序集 LxContracts(包括服务的数据契约Books.cs和操作契约IBookContract.cs)需要添加引用System.Runtime.Serialization 和System.ServiceModel:
Books.cs 代码
IBookContract.cs 代码
2、 程序集LxServices(包括服务类BookService.cs),需要引用项目中的程序集LxContracts:
BookService.cs 代码
3、 程序集 Host_Server 是WCF服务的控制台宿主程序,需要引用 System.ServiceModel 和项目中LxContracts 程序集与 LxServices程序集:
Program.cs 代码
App.config 配置文件代码
注意:<transport clientCredentialType="Certificate"/> 我们对客户端的认证方式修改成为了 Certificate
4、我们为项目添加一个Client1 控制台客户端程序,在启动 Host_Server 的情况下,我们添加服务引用:“https://lx-pc:9000/mex” ,服务引用命名为:“WCF.BookSrv”,并点击 “高级” 将集合类型选择为System.Collections.Generic.List。服务引用添加好之后,我们编写调用代码如下:
生成之后,启动服务器端 Host_Server,我们运行一下客户端Client1,报错,如下图所示:
因为我们在服务器端对客户端的认证方式为 Certificate,因此我们的客户端必须要提供一个证书,才能正常访问我们的服务,我们需要修改一下客户端Client1的 app.config 配置文件,在终结点的行为中指定我们客户端的证书,如下:
Client1 App.config 配置文件代码
再次运行客户端Client1,发现服务调用成功:
我们在解决方案中再添加一个Client2的控制台客户端,代码和Client1 一样,只不过配置文件中我们使用的是证书Client2-PC。我们运行Client2 发现服务也调用成功:
既然这样的话,我们能不能像自定义用户名和密码认证一样,对证书也进行检验呢。比如我们让服务对客户端证书进行认证的时候,让持有证书 Client1-PC 的客户端 不能访问,但可以让持有证书 Client2-PC 的客户端访问呢,是可以的,下面我们对服务进行一下改进
5、自定义客户端的认证:
我们依然需要对 LxService 程序集添加引用 System.IdentityModel 和System.IdentityModel.Selectors ,然后在该程序集中添加一个自定义证书的验证类 CustomCertificateVerification 并使其继承 X509CertificateValidator ,重写父类的 Validate 方法。在这个方法中,根据证书的指纹来对客户端提供的证书进行检验。
CustomCertificateVerification.cs 代码
之后,我们修改一下宿主程序Host_Server 的App.config 配置文件,将原来的
<serviceCredentials>
<serviceCertificate storeName="My" x509FindType="FindBySubjectName" findValue="Lx-PC" storeLocation="LocalMachine"/>
</serviceCredentials>
修改为:
<serviceCredentials>
<serviceCertificate storeName="My" x509FindType="FindBySubjectName" findValue="Lx-PC" storeLocation="LocalMachine"/>
<clientCertificate>
<authentication certificateValidationMode="Custom" customCertificateValidatorType="LxServices.CustomCertificateVerification,LxServices"/>
</clientCertificate>
</serviceCredentials>
使我们自定义的证书验证类生效。
我们重新生成一下代码,打开宿主程序Host_Server 的生成目录Bin/Debug,直接运行Host_Server.exe(不要调试运行,否则服务器端会抛出异常)。然后运行Client1 客户端,我们会发现 客户端 Client1 已经无法调用服务了:
我们运行一下客户端Client2,发现服务依然能够调用成功:
三、总结:
基于SSL的WCF传输安全实践,我们基本演示完成了,分别包括的匿名客户端访问,自定义用户名和密码客户端验证,使用X.509证书方式的客户端验证,在学习这方面知识的时候,自己查找了很多资料,再此将这些开发的步骤和关键点记录下来和大家分享,不足之处,希望大家多多指正。
重温WCF之WCF传输安全(十三)(4)基于SSL的WCF对客户端采用证书验证(转)的更多相关文章
- 基于SSL的WCF传输安全
[实践]WCF传输安全1:前期准备之证书制作 [实践]WCF传输安全2:基于SSL的WCF匿名客户端 [实践]WCF传输安全3:基于SSL的WCF对客户端验证 [实践]WCF传输安全4:基 ...
- 重温WCF之WCF传输安全(十三)(2)基于SSL的WCF匿名客户端(转)
转载地址:http://www.cnblogs.com/lxblog/archive/2012/09/13/2683514.html 这一篇我们利用上一篇制作的证书,来演示一个基于SSL的WCF服务, ...
- 重温WCF之WCF传输安全(十三)(3)基于SSL的WCF对客户端验证(转)
转载地址:http://www.cnblogs.com/lxblog/archive/2012/09/18/2690719.html 上文我们演示了,客户端对服务器端身份的验证,这一篇来简单演示一下对 ...
- WCF分布式开发步步为赢(4):WCF服务可靠性传输配置与编程开发
今天继续WCF分布式开发步步为赢系列的第4节:WCF服务可靠性传输配置与编程开发.这个章节,我们要介绍什么是WCF服务的可靠性传输,随便介绍网络协议的概念,Web Service为什么不支持可靠性传出 ...
- WCF 笔记 (2) - 传输泛型 List 对象
WCF 笔记 (2) - 传输泛型 List 对象 本帖介绍怎么在 WCF 中,在 Server-side 和 Client-side 之间,传递默认无法传输的 List<T>.List& ...
- C# WCF学习笔记(二)终结点地址与WCF寻址(Endpoint Address and WCF Addressing) WCF中的传输协议
URI的全称是 Uniform Rosource Identifire(统一资源标识),它唯一标识一个确定的网绐资源,同时也表示资源所处的位置及访问的方式(资源访问所用的网络协议). 对于Endpoi ...
- 使用Fiddler解析WCF RIA Service传输的数据
原文 http://www.cnblogs.com/wintersun/archive/2011/01/05/1926386.html 使用Fiddler 2 解析WCF RIA Service传输的 ...
- WCF技术剖析之二十三:服务实例(Service Instance)生命周期如何控制[下篇]
原文:WCF技术剖析之二十三:服务实例(Service Instance)生命周期如何控制[下篇] 在[第2篇]中,我们深入剖析了单调(PerCall)模式下WCF对服务实例生命周期的控制,现在我们来 ...
- 转:wcf大文件传输解决之道(1)
首先声明,文章思路源于MSDN中徐长龙老师的课程整理,加上自己的一些心得体会,先总结如下: 在应对与大文件传输的情况下,因为wcf默认采用的是缓存加载对象,也就是说将文件包一次性接受至缓存中,然后生成 ...
随机推荐
- Unity3D获取Andorid设备返回键,主页键等功能
在Unity开发中捕捉Android的常用事件其实很简单 在新建的脚本文件中就加入: 比如: // 返回键 if ( Application.platform == RuntimePlatform.A ...
- python 的dict的update 方法的一点诡秘的行为
如下: >>> 'a%s'%a 'a{1: 0, 2: 0}' >>> for k,v in a.items(): a.update(k=v) >>&g ...
- ulimit命令
原文链接 linux下默认是不产生core文件的,要用ulimit -c unlimited放开 概述 系统性能一直是一个受关注的话题,如何通过最简单的设置来实现最有效的性能调优,如何在有限资源的条件 ...
- Expression Add Operators
Given a string that contains only digits 0-9 and a target value, return all possibilities to add bin ...
- 开源工作流 Bonita BPM (JAVA)
Bonita BPM 开源工作流 Bonita BPM (JAVA) http://www.bonitasoft.com/
- C#操作txt文件
目的:txt文件的创建,读写操作 功能:创建一个winform窗体,当文件不存在时可以实现txt文件的创建 效果: 代码: 文件的创建(判断文件是否存在,不存在则创建新的文本文件): private ...
- Qt 常用的功能
1.程序重启 void Widget::reStart() { qApp->closeAllWindows(); QProcess::startDetached(qApp->appli ...
- DELPHI控件:DBLookupComboBOX组件的使用方法
在许多数据表中,数据是以代码方式存放的,如在班级编码数据表tB03(表5.5)中,系部字段TB0309采用编码方式存放,系部真实名称则存放在系部编码表TB06.使用代码的好处是,用户可在编码表TB06 ...
- MongoDB 副本集的原理、搭建、应用
概念: 在了解了这篇文章之后,可以进行该篇文章的说明和测试.MongoDB 副本集(Replica Set)是有自动故障恢复功能的主从集群,有一个Primary节点和一个或多个Secondary节点组 ...
- ffmpeg-20160701-git-bin.7z
ESC 退出 0 进度条开关 1 屏幕原始大小 2 屏幕1/2大小 3 屏幕1/3大小 4 屏幕1/4大小 S 下一帧 [ -2秒 ] +2秒 ; -1秒 ' +1秒 下一个帧 -> -5秒 f ...