最近做WCF开发,有个需求是在服务端做认证,网上查资料了解到可以用UserName和Password
来做认证,只需要写好配置文件和在服务端写好验证类就行了,但是网上普遍的博文都是需要用证书,而我自己却只想做个简单的认证不想用证书来增加传输的安全性。随后在网上浏览了很久都没有找到现成的例子,最后明白靠人不如靠己啊哈哈,于是决定自己好好研究下WCF的认证体系。
这里特别感谢蒋金楠老师的博客
http://www.cnblogs.com/artech/archive/2011/05/22/authentication_01.html
 
这篇博文从WCF的两种安全模式谈起,讲到WCF的安全体系主要包括三个方面:传输安全(Transfer Security)、授权或者访问控制(Authorization OR Access Control)以及审核(Auditing)。而传输安全又包括两个方面:认证(Authentication)和消息保护(Message
Protection)。认证帮助客户端或者服务确认对方的真实身份,而消息保护则通过签名和加密实现消息的一致性和机密性。WCF采用两种不同的机制来解决这三个涉及到传输安全的问题,我们一般将它们称为不同的安全模式,即Transport安全模式和Message安全模式。 这篇博文详细介绍了Transport ,Message 以及他们两种混合的Mixed模式,有兴趣的童鞋可以看看。
 
而我今天的任务就是要仔细研究下 在Transport模式和Message模式下的具体应用的异同,以便来实现上文所说的传输安全。
对于服务器,如果我们做传输安全的功能需要添加Binding的安全性设置和设置具体的服务器认证方式。如下,在配置文件中的设置:
<behavior name="metadataBehavior"> 
<serviceCredentials>
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="WCFTestService.CustomValidator, WCFTestService"/>
</serviceCredentials>
</behavior>
<binding name="basicHttpBinding" receiveTimeout="00:10:00">
<security
mode="TransportCredentialOnly">
           <transport clientCredentialType="Basic"></transport>
          </security>
</binding>

Binding的安全性设置

如上的配置文件中在我们的binding的元素属性中有个security的节点,我们在这个节点设置mode的值则是设置安全方式。WCF
提供了 5 种不同的安全方式:

None: 不采取任何安全措施,仅适合在内部安全环境使用。

Transport: 在传输协议级别上对通道的所有通讯进行加密,可使用的通讯协议包括 HTTPS、TCP、IPC 和 MSMQ。优点是应用广泛,多平台支持,实施方便简单,效率极高,适合高吞吐量的服务使用;缺点是只能实现点对点(point-to-point)的消息安全,在使用中介连接(Proxy)时可能会泄漏消息内容,比较适用于于
Intranet 或直接连接的环境。

Message: 通过相关标准(如 WS-Security)直接对消息进行加密来达到安全目的。优点是能实现端到端(end-to-end)的安全传输,不存在中介安全隐患,且扩展性较好。因采取工业安全标准,所以整合能力更强,适用于
Internet 服务。缺点是比 Transport 效率要低一些。

Mixed(TransportWithMessageCredential): 混合了上面两种方式。使用 Transport 方式完成消息完整性、消息机密性以及服务器认证,而使用 Message 方式完成客户端认证。
Both: 使用 Transport 和 Message 共同完成所有的安全过程,比较恐怖,性能低下,只有 NetMsmqBinding 支持这一安全方式
下图列出了各种类型bind对这5种安全方式的支持:

而对于BasicHttpBinding还具有一种特殊的方式TransportCredentialOnly,它只提供针对于HTTP的客户端认证,并不能提供消息一致性和机密性的保证。(当看到这种方式我就觉得应该是最满足于我的了)。

注:在我的测试中当我设置方式为Transport在服务端出错了,日志文件显示“提供的
URI 方案“http”无效,应为“https”。”,查阅资料才知道由于所有基于HTTP的绑定都通过HTTPS来实现Transport安全,所以当选择Transport和TransportWithMessageCredential安全模式的情况下,终结点地址必须是一个HTTPS地址,而我自己的终结点地址是设置的http。

安全性解决了消息的完整性和机密性,那么剩下来的就是认证 了。WCF 支持多种认证方式,允许我们从多个 "客户端验证类型(Client Credentials Types)" 中选择适合我们需求的方案,比如经典的 "用户名/密码",或者
"Windows 集成身份认证(NTLM 或 Kerberos)"、"X.509 数字证书" 等。 接下来我们来看看客户端凭证,这也就是对应在security节点下的元素节点,分为message和transport。

基于Transport的客户端凭证

我们需要设置clientCredentialType 来确定客户端凭证的类型,它拥有六种不同的客户端用户凭证类型体现了服务端针对客户端不同的认证方式:

None:客户端无需指定用户凭证,即匿名认证。此为默认值;

Basic:采用Basic认证方式进行客户端认证。在这种认证方式下,客户端需要提供有效的用户名和密码,但是仅仅采用较弱的方式对密码进行加密。所以当且仅当你确定客户端和服务端之间的连接绝对安全的前提下,你才能用这种认证方式;

Digest:采用Digest认证方式进行客户端认证。Digest认证提供与Basic一样的认证功能,但是在安全性上有所提升。主要体现并不是直接将用户名和密码直接进行网络传输,而是对其进行哈希计算(MD5)得到一个哈希码(此过程又称为Message
Digest),最终传输的是该哈希码;

Ntlm:表示使用基于NTLM方式的Windows集成认证方式对客户端进行认证;

Windows:表示使用Windows集成认证的方式对客户端进行认证。如果能够使用Kerberos,则直接采用Kerberos进行认证,否则才使用NTLM;

Certificate:表示客户端的身份通过一个X.509数字证书表示,服务端通过校验证书的方式来确定客户端的真实身份。

基于Message模式的客户端凭证

我们需要设置clientCredentialType
来确定客户端凭证的类型,它拥有两种不同的客户端用户凭证类型体现了服务端针对客户端不同的认证方式UserName和Certificate
它们分别代表基于用户名/密码的凭证和针对X.509证书的凭证。在默认的情况下采用用户名/密码的凭证。
关于上述的两种客户端凭证,UserName只能用在Mixed模式下。当你选择了Message模式,则只能选择Certificate。
总结
放上两张图,第一张是系统预定义绑定类型对transport客户端凭证的支持,第二张是系统预定义绑定类型对message客户端凭证的支持

用户名/密码认证模式

在前文提到过,认证模式对于Transport和Message有稍许的不同,但都包括windows,UserName和Certificate,因为我的目的就是用UserName来解决问题,所以就只严爵了下UserName的模式。

用户名/密码凭证在客户端的设置很容易,但是我们关心的是服务端采用怎样的机制来验证这个凭证。WCF为你提供了如下三种方式来验证凭证中用户名是否和密码相符:

Windows:将用户名和密码映射为Windows帐号和密码,采用Windows认证;

MembershipProvider:利用配置的MembershipProvider验证用户名和密码;

自定义:通过继承抽象类UsernamePasswordValidator,自定义用户名/密码验证器进行验证。

我采用的是自定义,继承抽象类UsernamePasswordValidator,重写方法Validate来自定义验证规则,最后在配置文件中behavior节点的元素属性中配置

<span style="font-size:18px;"><serviceCredentials>
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="WCFTestService.CustomValidator, WCFTestService"/>
</serviceCredentials></span>

customUserNamePasswordValidatorType 包括两部分前面是自定义验证类的完全限定名,中间是逗号,最后是命名空间。

最后则是来完成自己的目标了,我设置security mode为TransportCredentialOnly ,然后用基于transport模式的客户端凭证,clientCredentialType设置为“Basic”,具体配置可以参见文章开头。OK 服务器大功告成。

剩下的就是客户端了,客户端来说相对要简单的多,配置文件中添加

<span style="font-size:18px;"><span style="font-family:FangSong_GB2312;"> <binding name="basicBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic"/>
</security>
</binding></span></span>

客户端调用方面需要提供UserName和Password

<span style="font-size:18px;"><span style="font-family:FangSong_GB2312;">using (ChannelFactory<IService> channelFactory = new ChannelFactory<IService>("service"))
{
IService proxy = channelFactory.CreateChannel();
UserNamePasswordClientCredential credential = channelFactory.Credentials.UserName; credential.UserName = "Admin";
credential.Password = "123456"; </span></span>

终于写完了,也算对这一天工作的一个总结。接下来我会写一点关于服务器契约方面的问题,记录我工作当中遇到的问题,还有WCF服务器诊断。

(WCF初体验)WCF的认证和消息保护的更多相关文章

  1. WCF初体验(C#操作Exchange)

    最近再做一个Exchange的客户端维护工具,遇到了很多问题. 由于刚接触C#和Exchange,所以还需要继续学习.在此记录一下,只是一个新手的记录. 环境:         服务器:Exchang ...

  2. (WCF初体验)WCF服务器诊断

    WCF服务器搭建好之后,不管是客户端访问还是本地调试,出个问题抛出来的原因往往在我们看来都是不知所以然的,更可能是跑出来的问题和真正的问题差了很远,比如"通信对象 System.Servic ...

  3. Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务、WCF消息头添加安全验证Token

    原文:Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务.WCF消息头添加安全验证Token 为什么选择wcf?   因为好像wcf和wpf就是哥俩,,, 为什么选择异步 ...

  4. 【阿里云产品公测】消息队列服务MQS java SDK 机器人应用初体验

    [阿里云产品公测]消息队列服务MQS java SDK 机器人应用初体验 作者:阿里云用户啊里新人   初体验 之 测评环境 由于MQS支持外网访问,因此我在本地做了一些简单测试(可能有些业余),之后 ...

  5. WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化

    原文:WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化 [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制 ...

  6. WCF初见之SQL数据库的增删改查

    1.首先要连接数据库,自然要有数据库啦,创建一个数据库表Login,并插入一个数据: --创建数据库表login CREATE TABLE Login ( UName VARCHAR(20) PRIM ...

  7. JMS服务器ActiveMQ的初体验并持久化消息到MySQL数据库中

    JMS服务器ActiveMQ的初体验并持久化消息到MySQL数据库中 一.JMS的理解JMS(Java Message Service)是jcp组织02-03年定义了jsr914规范(http://j ...

  8. YII学习,初体验 ,对YII的一些理解.

    先说点没用的: 不会选择,选择后不坚持,不断的选择.这是人生中的一个死循环,前两一直迷茫.觉得自己前进方向很不明朗.想去学的东西有很多.想学好YII,想学PYTHON 想学学hadoop什么的,又想研 ...

  9. Spring boot集成Rabbit MQ使用初体验

    Spring boot集成Rabbit MQ使用初体验 1.rabbit mq基本特性 首先介绍一下rabbitMQ的几个特性 Asynchronous Messaging Supports mult ...

随机推荐

  1. Hibernate统计表中的条数

     /** * 判断积分日志表中是否有某个用户的注册日志 */@Transactional(propagation = Propagation.REQUIRED)public boolean isE ...

  2. CentOS 7下的Vim自动补齐插件YouCompleteMe安装及配置

    备注:现在对于 YouCompleteMe 的安装应采用更为简单的方法,即利用 Vundle 来安装这个插件.具体方法可见: Vundle 主页 YouCompleteMe 主页 而 .vimrc 的 ...

  3. 【cocos 2d-x】VS2013+cocos2d-x3.3Final+Adriod交叉编译环境配置(超详细版)

    本系列文章由@二货梦想家张程 所写,转载请注明出处. 作者:ZeeCoder  微博链接:http://weibo.com/zc463717263 我的邮箱:michealfloyd@126.com ...

  4. PS 图像调整算法——自动对比度 (Auto Contrast)

    PS 给出的定义: Enhance Monochromatic Contrast: Clips all channels identically. This preserves the overall ...

  5. 苹果新的编程语言 Swift 语言进阶(十三)--类型检查与类型嵌套

    一 类型检查 1. 类型检查操作符 类型检查用来检查或转换一个实例的类型到另外的类型的一种方式. 在Swift中,类型检查使用is和as操作符来实现. is操作符用来检查一个实例是否是某种特定类型,如 ...

  6. 软件工程师 Book

    一.软件工程师  --Clean Code<代码整洁之道>  --Implementation Patterns<实现模式>  --Code Complete<代码大全& ...

  7. OpenCV——彩色图像转成灰度图像

    // PS_Algorithm.h #ifndef PS_ALGORITHM_H_INCLUDED #define PS_ALGORITHM_H_INCLUDED #include <iostr ...

  8. onDraw(canvas)和dispatchDraw(canvas)方法

    绘制VIew本身的内容,通过调用View.onDraw(canvas)函数实现 绘制自己的孩子通过dispatchDraw(canvas)实现 View组件的绘制会调用draw(Canvas canv ...

  9. LeetCode之旅(17)-Ugly Number

    题目: Write a program to check whether a given number is an ugly number. Ugly numbers are positive num ...

  10. LeetCode(45)-Bulls and Cows

    题目: You are playing the following Bulls and Cows game with your friend: You write down a number and ...