在webSservice时代,可以通过SOAPHEADER的方式很容易将用户名、密码附加到SOAP header消息头上,用户客户端对调用客户端身份的验证。在WCF 时代,也可以通过OperationContext.Current.IncomingMessageHeaders的方式将用户名、密码附加到SOAP消息中。但是这种方式实现起来有个缺点;那就是所有调用客户端都需要这样做才能将我们需要通过认证的帐号、密码附加到SOAP消息上。实际上,也可以通过WCF扩展的方式,在客户端自动将用户名、密码附加到SOAP消息中。这即是本文主题。

1、客户端消息自动附加用户名、密码
  实现IClientMessageInspector接口,用于附加调用者的账号、密码信息

  1. public class ClientMessageInspector : IClientMessageInspector
  2. {
  3. public void AfterReceiveReply(ref Message reply, object correlationState)
  4. {
  5.  
  6. }
  7.  
  8. public object BeforeSendRequest(ref Message request, IClientChannel channel)
  9. {
  10. MessageHeader userNameHeader = MessageHeader.CreateHeader("OperationUserName", "http://tempuri.org", "account", false, "");
  11. MessageHeader pwdNameHeader = MessageHeader.CreateHeader("OperationPwd", "http://tempuri.org", "password", false, "");
  12. request.Headers.Add(userNameHeader);
  13. request.Headers.Add(pwdNameHeader);
  14. Console.WriteLine(request);
  15. return null;
  16. }
  17. }

2、实现IEndpointBehavior 接口。用户将客户端的消息检查器添加到clientruntime的消息检查器集合中.注意,以下代码中为了简单将服务端分发消息检查器也添加到服务端终结点分发器(EndpointDispatcher)的分发运行时的消息检查器中。

  1. public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
  2. {
  3.  
  4. }
  5.  
  6. public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
  7. {
  8. clientRuntime.MessageInspectors.Add(new ClientMessageInspector());//客户端使用
  9. }
  10.  
  11. public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
  12. {
  13. endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MessageDispatcher());//服务端使用
  14. }
  15.  
  16. public void Validate(ServiceEndpoint endpoint)
  17. {
  18.  
  19. }

3、实现抽象类BehaviorextensionElement.用于在配置文件中配置对WCF服务行为的扩展

  1. internal class MessageBindingElement : BehaviorExtensionElement
  2. {
  3. public override Type BehaviorType
  4. {
  5. get { return typeof (MessageEndpointBehavior); }
  6. }
  7.  
  8. protected override object CreateBehavior()
  9. {
  10. return new MessageEndpointBehavior();
  11. }
  12. }

4、服务端验证客户端的账号、密码

实现IDispatcherMessageInspector

  1. public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
  2. {
  3. Console.WriteLine(request);
  4. string userName = GetHeaderValue("OperationUserName");
  5. string pwd = GetHeaderValue("OperationPwd");
  6. if ("account" == userName && "password" == pwd)
  7. {
  8. return null;
  9. }
  10. throw new Exception("用户名、密码错误");
  11. }
  12.  
  13. public void BeforeSendReply(ref Message reply, object correlationState)
  14. {
  15.  
  16. }
  17.  
  18. string GetHeaderValue(string key)
  19. {
  20. int index = OperationContext.Current.IncomingMessageHeaders.FindHeader(key, "http://tempuri.org");
  21. if (index >= )
  22. {
  23. return OperationContext.Current.IncomingMessageHeaders.GetHeader<string>(index).ToString();
  24. }
  25. return null;
  26. }

5、服务端配置;

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <configuration>
  3. <system.serviceModel>
  4. <extensions>
  5. <behaviorExtensions>
  6. <add name="messageInterptor" type="MessageInterceptor.MessageBindingElement,MessageInterceptor"/>
  7. </behaviorExtensions>
  8. </extensions>
  9. <behaviors>
  10. <endpointBehaviors>
  11. <behavior name="messageBehavior">
  12. <messageInterptor />
  13. </behavior>
  14. </endpointBehaviors>
  15. </behaviors>
  16. <services>
  17. <service name="Services.CalculatorService">
  18. <endpoint address="net.tcp://127.0.0.1:8081/CalculateService"
  19. binding="netTcpBinding"
  20. contract="Contracts.ICalculator"
  21. behaviorConfiguration="messageBehavior"></endpoint>
  22. </service>
  23. </services>
  24. </system.serviceModel>
  25. </configuration>

6、客户端配置;

  1. <?xml version="1.0"?>
  2. <configuration>
  3. <system.serviceModel>
  4. <client>
  5. <endpoint name="calculatorService"
  6. address="net.tcp://127.0.0.1:8081/CalculateService"
  7. binding="netTcpBinding"
  8. contract="Contracts.ICalculator"
  9. behaviorConfiguration="messageBehavior">
  10. </endpoint>
  11. </client>
  12. <extensions>
  13. <behaviorExtensions>
  14. <add name="messageInterptor" type="MessageInterceptor.MessageBindingElement,MessageInterceptor"/>
  15. </behaviorExtensions>
  16. </extensions>
  17. <behaviors>
  18. <endpointBehaviors>
  19. <behavior name="messageBehavior">
  20. <messageInterptor />
  21. </behavior>
  22. </endpointBehaviors>
  23. </behaviors>
  24. </system.serviceModel>
  25. </configuration>

7、运行结果图;

服务端;

客户端;

WCF安全:通过 扩展实现用户名密码认证的更多相关文章

  1. WCF的用户名+密码认证方式(转)

    概述 今天在做Master Data Service(后面简称MDS)项目时需要通过WCF来使用MDS的API,从而对MDS的数据进行操作.在这个过程中,遇到了一个棘手的问题,就是在客户端调用Web ...

  2. WCF身份验证之用户名密码认证

    WCF支持多种认证技术,例如Windowns认证.X509证书.Issued Tokens.用户名密码认证等,在跨Windows域分布的系统中,用户名密码认证是比较常用的,要实现用户名密码认证,就必须 ...

  3. Nginx实战之让用户通过用户名密码认证访问web站点

    1.Nginx实战之让用户通过用户名密码认证访问web站点 [root@master ~]# vim /usr/local/nginx/conf/extra/www.conf server { lis ...

  4. nginx让用户通过用户名密码认证访问web页面

    在使用nginx转发的时候,要进行一次用户身份的确认. 1)通过htpasswd命令生成用户名及对应密码数据库文件. [root@bgs-5p173-wangwenting ~]# htpasswd ...

  5. 启动Nginx目录浏览功能及 让用户通过用户名密码认证访问web站点

    一.启动Nginx目录浏览功能  [root@abcdocker extra]# cat w.conf server { listen 80; server_name IP地址; location / ...

  6. Geoserver通过ajax跨域访问服务数据的方法(含用户名密码认证的配置方式)

    Goeserver数据有两种,一种需进行用户密码的权限认证,一种无须用户密码.对于网上跨域访问Geoserver数据的种种方法,对这2种数据并非通用. 笔者将Geoserver官方下载的Geoserv ...

  7. WCF之添加自定义用户名密码认证

    1.创建WCF服务应用以及调用客户端(请自行google).  2.创建X509证书       cmd 进入  C:\Program Files\Microsoft SDKs\Windows\v6. ...

  8. Nginx之让用户通过用户名密码认证访问web站点

    有时我们会有这么一种需求,就是你的网站并不想提供一个公共的访问或者某些页面不希望公开,我们希望的是某些特定的客户端可以访问. 那么我们可以在访问时要求进行身份认证,就如给你自己的家门加一把锁,以拒绝那 ...

  9. squid添加用户名密码认证

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html 内部邀请码:C8E245J (不写邀请码,没有现金送) 国 ...

随机推荐

  1. docker-compose教程(安装,使用, 快速入门)

    1.Compose介绍Docker Compose是一个用来定义和运行复杂应用的Docker工具.一个使用Docker容器的应用,通常由多个容器组成.使用Docker Compose不再需要使用she ...

  2. logstash 中多行合并

    这里我之前是在input里面配置的多行合并,合并语法为: input { beats { type => beats port => 7001 codec => multiline ...

  3. ELK 的插件安装(head)

    这里我装了一个head插件和kopf的插件 ./plugin install mobz/elasticsearch-head ./plugin install lmenezes/elasticsear ...

  4. php分享二十五:跨域请求

    问题: 跨域请求有几种方式? jsonp支持哪几种请求方式? 支持post请求吗? 支持get请求吗? 由于浏览器同源策略,凡是发送请求url的协议.域名.端口三者之间任意一与当前页面地址不同即为跨域 ...

  5. CSS加DIV布局

    第一种: <div> <div class="right"> <p></p> <p></p> <p&g ...

  6. JS 在 IE9 中出现奇怪的错误(参数是必选项 argument not optional)

    最近发现之前运行正常的网站,在 IE9 下会报这个错误.网上查了一下,发现是跟我的方法名字有关... 我起了一个叫做 addFilter 名字的方法,但是很不巧,IE9 里也有一个这个名字的方法,所以 ...

  7. 如何在Linux平台下安装JDK

    原文链接:http://android.eoe.cn/topic/android_sdk 1.下载Java的开发包JDK: JDK有好几个类型版本,我们只需要选择Java SE类型的版本就行了. 进入 ...

  8. DBUtils查找最大的ID总是返回0

    1.实体: public class Order { private int id; private Date orderDate; public int getId() { return id; } ...

  9. 未能为数据库 '*'中得对象'*'分配空间,因文件组'PRIMARY'已满

    服务器使用mssqlserver2005,最近经常出现无法新增信息错误,查看日志,发现严重错误提示,内容大致为: 无法为数据库 'weixin_main' 中的对象 'dbo.wx_logs'.'PK ...

  10. 每日英语:Are Smartphones Turning Us Into Bad Samaritans?

    In late September, on a crowded commuter train in San Francisco, a man shot and killed 20-year-old s ...