WCF身份验证三:自定义身份验证之<MessageHeader>
关于使用SoadHeader验证Robin已经有一篇十分精彩的文章: WCF进阶:为每个操作附加身份信息, 不过我的思维方式总是跟别人有点不太一样, 还是把类似的内容用我的方式重新组织一下.
使用Header验证最直接的想法就是不要使用证书, 证书在很多场合都显得太过于复杂了, 而我们对安全性的要求并没有那么高, 毕竟我们周围的环境中有能力截取网络中的通信数据并筛选中敏感信息, 而且有动机加以利用破坏的人怎么看都像是还没出生.
下面开始演练:
打开vs, 创建一个新的WCF Service Library, 我保持了它的默认名字WcfServiceLibrary4, 然后向解决方案添加一个windows forms application, 名字为WindowsFormsApplication1, 作为我们的客户端, 在客户端添加服务引用, 直接点discover, 即可引用我们刚创建的WcfServiceLibrary4, 如图所示:
然后在客户端窗体上拖一个按钮, 给它的点击事件写两行代码以调用服务:
private void button1_Click(object sender, EventArgs e)
{
var proxy = new ServiceReference1.Service1Client();
MessageBox.Show(proxy.GetData(3));
}
运行一下, 会看到服务被正确执行了.
现在开始添加身份验证的逻辑. 首先, 对客户端来说, 基本思想是每发出一个服务请求之前, 添加一个header, 所以就有了如下这个类:
public class MyInspector : IClientMessageInspector
{
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
} public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
request.Headers.Add(MessageHeader.CreateHeader("Password", "gb", "123"));
return null;
}
}
这个类只是简单继承了IClientMessageInspector接口, 并添加了一个MessageHeader, 明显它不可能直接就起作用, 需要另一个机制把它与服务请求绑定起来, 于是就有了下面这个类:
public class MyEndPointBehavior : IEndpointBehavior
{ public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
} public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new MyInspector());
} public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
} public void Validate(ServiceEndpoint endpoint)
{
}
}
这个类负责将刚创建的Inspector添加到EndPoint的behavior当中, 但是这个类自身仍然是悬空的, 所以继续(这个类需要引用System.Configuration):
public class MyBehaviorExtension : BehaviorExtensionElement
{ public override Type BehaviorType
{
get { return typeof(MyEndPointBehavior); }
} protected override object CreateBehavior()
{
return new MyEndPointBehavior();
}
}
再创建一个Extension类, 负责把MyEndPointBehavior类与当前的服务实例关联起来, 但是同样的问题, 这个类自身还没有被调用, ----不用再创建下一个类了, 这个类将通过app.config与服务进行绑定:
在app.config的system.serviceModel下, 添加一个自定义的behavior:
然后将已有的endPoint与此behavior关联起来:
此EndPoint的配置中只有蓝框里面是手动新增的, 其它都是自动生成. 现在这个空的behavior已经被应用到了具体的endpoint, 接下来需要把这个behavior具体化, 先来增加一个extension:
<extensions>
<behaviorExtensions>
<add name="myExtension" type="WindowsFormsApplication1.MyBehaviorExtension, WindowsFormsApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
需要注意的是, 这个extension的type必须是我们刚才最后添加的那个MyBehaviorExtension类的AssemblyQualifiedName, 并且中间不允许有任何的空格, 回车等.
接下来, 将这个extension与空的behavior关联起来:
关联的方法很简单, 就是增加一个节点, 名字就是新增加的extension的Name.
现在, 我们终于全线贯通了, 出发点是endpoint, 为默认的endpoint增加一个behavior, 这个behavior有一个我们自定义的extension, 这个extension会创建一个自定义的endpointbehavior, 在这里最终添加了inspector. 来测试一下吧: 在inspector中下一个断点, 执行程序, 会发现断点确实被执行了, 至此, 客户端的配置就结束了, 每一次调用服务时, 都会附加一个名为Password的header, 这就是我们的目的.
然后是服务端, 服务端需要检测是否传递了password, password的值是否正确, 如果正确才会继续提供服务. 总的流程与客户端基本一致, 唯一的区别是将IClientMessageInspector换成了IDispatchMessageInspector, 具体的几个类的代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration; namespace WcfServiceLibrary4
{
class MyInspector : IDispatchMessageInspector
{ public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
if (request.Headers.FindHeader("Password", "gb") < 0 ||
request.Headers.GetHeader<string>("Password", "gb") != "123")
throw new UnauthorizedAccessException();
return null;
} public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
}
} public class MyEndPointBehavior : IEndpointBehavior
{ public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
} public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
} public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MyInspector());
} public void Validate(ServiceEndpoint endpoint)
{
}
} public class MyBehaviorExtension : BehaviorExtensionElement
{ public override Type BehaviorType
{
get { return typeof(MyEndPointBehavior); }
} protected override object CreateBehavior()
{
return new MyEndPointBehavior();
}
} }
App.config 的配置和客户端基本上完全相同, 只有最终的extension的type换成服务端的类型全名即可.
然后重新运行项目, 在服务端的检查口令的地方下个断点, 可以确定这里被运行到了, 这就全部完工了.
当然, 也可以把这服务端和客户端总共用到的三个接口, 一个基类全部合在一个类中实现, (比如Robin的实现) 这样可以在客户端和服务端之间共享代码, 以及类名就只剩一个了, 不过我觉得还是按它本来的面目拆开来写比较容易理解, 至于理解了之后如何优化, 那就完全自由发挥了.
WCF身份验证三:自定义身份验证之<MessageHeader>的更多相关文章
- jQuery Validate 表单验证插件----自定义一个验证方法
一.下载依赖包 网盘下载:https://yunpan.cn/cryvgGGAQ3DSW 访问密码 f224 二.引入依赖包 <script src="../../scripts/j ...
- EasyUI表单验证,自定义插件验证,自定义js插件验证,远程验证,常见手机号,中英文,qq等验证规则验证
{ field : 'startPort', title : "起始端口", editor: "text", width : 50, editor: { ...
- jQuery Validation Engine 表单验证,自定义规则验证方法
jQuery Validation Engine 表单验证说明文档http://code.ciaoca.com/jquery/validation-engine/ js加到jquery.validat ...
- ExtJs 自定义Vtype验证
最近公司开发项目在用ExtJs,碰到验证的就大概的总结了一些常用的验证.自定义的验证主要有两种方式:一种是单字段的自定义验证,另一种是多字段间的验证.对于单字段的验证主要通过regex配置项指定自定义 ...
- MVC身份验证.MVC过滤器.MVC6关键字Task,Async.前端模拟表单验证,提交.自定义匿名集合.Edge导出到Excel.BootstrapTree树状菜单的全选和反选.bootstrap可搜索可多选可全选下拉框
1.MVC身份验证. 有两种方式.一个是传统的所有控制器继承自定义Control,然后再里面用MVC的过滤器拦截.所以每次网站的后台被访问时.就会先走入拦截器.进行前端和后端的验证 一个是利用(MVC ...
- webservice安全性之 SoapHeader自定义身份验证
相信很多开发者都用过WebService来实现程序的面向服务,本文主要介绍WebService的身份识别实现方式,当然本文会提供一个不是很完善的例子,权当抱砖引玉了. 首先我们来介绍webservic ...
- socketserver模块三次登陆验证,身份验证
帅爆太阳的男人 1,socketserver是解决TCP服务器和多个客户端进行通信 服务器: import socketserver class MySocket(socketserver,BaseR ...
- SSL/TLS/WTLS原理(密钥协商的形象化比喻:验证服务器的身份,用服务器的公钥协商加密格式,然后再加密具体的消息,TCP传递SSL处理后的数据)good
一 前言 首先要澄清一下名字的混淆: 1 SSL(Secure Socket Layer)是netscape公司设计的主要用于web的安全传输协议.这种协议在WEB上获得了广泛的应用. 2 IETF( ...
- [置顶] Web用户的身份验证及WebApi权限验证流程的设计和实现 (不是Token驗證!!!不是Token驗證!!!都是基於用户身份的票据信息驗證!!!)
转发 http://blog.csdn.net/besley/article/details/8516894 不是Token驗證!!!不是Token驗證!!!都是基於用户身份的票据信息驗證!!! [ ...
- WCF 安全性 之 自定义证书验证
案例下载 http://download.csdn.net/detail/woxpp/4113172 客户端调用代码 通过代理类 代理生成 参见 http://www.cnblogs.com/woxp ...
随机推荐
- (转)阿里巴巴Druid数据源及使用
原文链接:https://blog.csdn.net/yanguo110/article/details/68944659 第一部分:数据源的集中比较. 目前常用的数据源主要有c3p0.dbcp.pr ...
- 配置vue-devtools调试工具
1. 通过 Git 克隆项目到本地 git clone https://github.com/vuejs/vue-devtools.git 2. Git 进入到 vue-devtools 所在目录,然 ...
- ECSHOP和SHOPEX快递单号查询EMS插件V8.6专版
发布ECSHOP说明: ECSHOP快递物流单号查询插件特色 本ECSHOP快递物流单号跟踪插件提供国内外近2000家快递物流订单单号查询服务例如申通快递.顺丰快递.圆通快递.EMS快递.汇通快递.宅 ...
- PHP (Yii2) 自定义业务异常类(可支持返回任意自己想要的类型数据)
public function beforeAction($action) { return parent::beforeAction($action); } public function runA ...
- python应用:异常处理
Python的错误异常在大部分IDE编辑器中则可以直接显示出来,便于开发人员的调试及修改工作,对初学者也比较友好. Python中包含错误和异常两种情况,错误主要是常见的语法错误SyntaxError ...
- numpy数组用法大全
机器学习的最基础模块就是numpy模块了,而numpy模块中的数组操作又是重中之重,所以我们要把数组的各种方法弄得明明白白的,以下就是数组的一些常用方法 1.创建各种各样的数组: import num ...
- python学习之面向对象程序设计的一些思考
将属于一类的对象放在一起: 如果一个函数操纵一个全局变量,那么两者最好都在类内作为特性和方法实现. 不要让对象过于亲密: 方法应该只关心自己实例的特性,让其他实例管理自己的状态. 简单就好: 让方法小 ...
- 分享一个根据具体的日期判断星座的PHP函数
其实原理很简单,也就是把所有的星座月份日期范围存储到一个数组中,然后根据日期判断属于哪个范围,这样就得到是哪个星座了. 下面的这个函数写的比较精炼,可以参考一下 function constellat ...
- PHP json_decode返回null解析失败原因
在PHP5.4之前 json_decode函数有两个参数json_decode有两个参数,第一个是待解析的字符串,第二个是是否解析为Array json_decode要求的字符串比较严格:(1)使用U ...
- LeetCode:14. Longest Commen Prefix(Easy)
1. 原题链接 https://leetcode.com/problems/longest-common-prefix/description/ 2. 题目要求 给定一个字符串数组,让你求出该数组中所 ...