前面两篇文章WCF进阶:将编码后的字节流压缩传输WCF 进阶: 对称加密传输都是实现了自定义编码,那两个例子中托管服务或者客户端调用都采用的代码实现,WCF更友好的方式是在app.config或web.config来配置服务的运行和调用,本文是介绍如何在配置文件中配置自定义的BindingElement。

上文WCF 进阶: 对称加密传输中我们实现了一个自定义的BindingElement:CryptEncodingBindingElement,它是一个MessageEncodingBindingElement,在宿主程序中,我们通过代码的方式将其添加到CustomBinding中去,方法为:

ICollection<BindingElement> bindingElements = new List<BindingElement>();
HttpTransportBindingElement httpBindingElement = new HttpTransportBindingElement();
string key = "JggkieIw7JM=";
string iv = "XdTkT85fZ0U=";
CryptEncodingBindingElement textBindingElement = new CryptEncodingBindingElement(new BinaryMessageEncodingBindingElement(), key, iv);
bindingElements.Add(textBindingElement);
bindingElements.Add(httpBindingElement);
CustomBinding bind = new CustomBinding(bindingElements);

如果是缺省的BindingElement,如TextMessageEncodingElement,HttpTransportElement,ReliableSessionElement,SecurityElement都可以像如下这样的方式进行配置:

<bindings>
<customBinding>
<binding name="myBinding">
<textMessageEncoding/>
<reliableSession/>
<security/>
<httpTransport/>
</binding>
</customBinding>
</bindings>

如果要想让我们自定义的BindingElement和上面的一样享受同等待遇的话,我们需要再额外做一些事情,那就是重载BindingElementExtensionElement,在.Net中扩展配置的基类为:ConfigurationElement,它定义声明了一些扩展配置的属性和方法,为了方便WCF重载了ConfigurationElement形成了ServiceModelExtensionElement,而为了进一步的方便扩展BindingElement,又提供了BindingElementExtensionElement的基类,创建自定义的BindingElementExtension,只需要重载BindingElementExtensionElement三个方法:

using System;
using System.ServiceModel.Channels; namespace System.ServiceModel.Configuration
{
// 摘要:
// 为使用计算机或应用程序配置文件中的自定义 System.ServiceModel.Channels.BindingElement 实现提供支持。
public abstract class BindingElementExtensionElement : ServiceModelExtensionElement
{
// 摘要:
// 初始化 System.ServiceModel.Configuration.BindingElementExtensionElement 类的新实例。
protected BindingElementExtensionElement(); // 摘要:
// 在派生类中重写时,获取表示自定义绑定元素的 System.Type 对象。
//
// 返回结果:
// 一个表示自定义绑定类型的 System.Type 对象。
public abstract Type BindingElementType { get; } // 摘要:
// 将指定绑定元素的内容应用到此绑定配置元素。
//
// 参数:
// bindingElement:
// 一个绑定元素。
//
// 异常:
// System.ArgumentNullException:
// bindingElement 为 null。
public virtual void ApplyConfiguration(BindingElement bindingElement);
//
// 摘要:
// 在派生类中重写时,返回一个自定义绑定元素对象。
//
// 返回结果:
// 一个自定义 System.ServiceModel.Channels.BindingElement 对象。
protected internal abstract BindingElement CreateBindingElement();
//
// 摘要:
// 使用指定绑定元素的内容来初始化此绑定配置节。
//
// 参数:
// bindingElement:
// 一个绑定元素。
protected internal virtual void InitializeFrom(BindingElement bindingElement);
}
}

public abstract Type BindingElementType { get; } 这个属性中只需要返回自定义类的类型,protected internal abstract BindingElement CreateBindingElement()的重载就是在这创建需要的自定义BindingElement,如果自定义的BindingElement有额外的属性或者参数,我们可以还可以通过创建带有ConfigurationPropertyAttribute的属性来指定。这个是.Net配置中的通性。在我们的需求中,需要一个CryptEncodingBindingElement实例,而CryptEncodingBindingElement带有三个参数:InnerMessageEncodingBindingElement,Key,IV。分析到这,我们的自定义BindingElement配置扩展类就成形了,代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Configuration;
using System.Configuration; namespace RobinLib
{
public class CryptEncodingBindingElementConfiguration : BindingElementExtensionElement
{
public override void ApplyConfiguration(System.ServiceModel.Channels.BindingElement bindingElement)
{
CryptEncodingBindingElement bind = bindingElement as CryptEncodingBindingElement;
if (InnerMessageEncoding.ToLower() == "text")
{
bind.InnerMessageEncodingBindingElement = new System.ServiceModel.Channels.TextMessageEncodingBindingElement();
}
else if (InnerMessageEncoding.ToLower() == "binary")
{
bind.InnerMessageEncodingBindingElement = new System.ServiceModel.Channels.BinaryMessageEncodingBindingElement();
}
else if (InnerMessageEncoding.ToLower() == "mtom")
{
bind.InnerMessageEncodingBindingElement = new System.ServiceModel.Channels.MtomMessageEncodingBindingElement(); }
bind.Key = Key;
bind.IV = IV;
base.ApplyConfiguration(bindingElement);
} [ConfigurationProperty("innerMessageEncoding",DefaultValue="text")]
public string InnerMessageEncoding
{
get
{
return base["innerMessageEncoding"] as string;
}
set
{
base["innerMessageEncoding"] = value;
}
} [ConfigurationProperty("key", DefaultValue = "")]
public string Key
{
get
{
return base["key"] as string;
}
set
{
base["key"] = value;
}
} [ConfigurationProperty("iv", DefaultValue = "")]
public string IV
{
get
{
return base["iv"] as string;
}
set
{
base["iv"] = value;
}
} public override Type BindingElementType
{
get { return typeof(CryptEncodingBindingElementConfiguration); }
} protected override System.ServiceModel.Channels.BindingElement CreateBindingElement()
{
if (InnerMessageEncoding.ToLower() == "text")
{
CryptEncodingBindingElement bindElement = new CryptEncodingBindingElement(new System.ServiceModel.Channels.TextMessageEncodingBindingElement(), Key, IV);
return bindElement;
}
else if (InnerMessageEncoding.ToLower() == "binary")
{
CryptEncodingBindingElement bindElement = new CryptEncodingBindingElement(new System.ServiceModel.Channels.BinaryMessageEncodingBindingElement(), Key, IV);
return bindElement;
}
else if (InnerMessageEncoding.ToLower() == "mtom")
{
CryptEncodingBindingElement bindElement = new CryptEncodingBindingElement(new System.ServiceModel.Channels.MtomMessageEncodingBindingElement(), Key, IV);
return bindElement;
}
throw new Exception("只支持Text,Binary,MTOM三种内置编码器!");
}
}
}

重载实现之后,我们就可以使用它在App.Config或者Web.Config来配置BindingElement,使用的方法为:

1. 在<system.serviceModel><extensions> <bindingElementExtensions>中添加新的配置节点的绑定。

2. 创建新的注册后的节点到自定义绑定中。

来看一下服务的配置文件吧:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<clear/>
<service name="Robin_Wcf_CustomMessageEncoder_SvcLib.Service1">
<host>
<baseAddresses>
<add baseAddress="http://127.0.0.1:8081/"/>
</baseAddresses>
</host>
<endpoint address="Robin_Wcf_Formatter" name="ep" contract="Robin_Wcf_CustomMessageEncoder_SvcLib.IService1" binding="customBinding" bindingConfiguration="myBinding"></endpoint>
</service>
</services>
<bindings>
<customBinding>
<binding name="myBinding">
<cryptMessageEncoding key="JggkieIw7JM=" iv="XdTkT85fZ0U=" innerMessageEncoding="Binary"/>
<httpTransport/>
</binding>
</customBinding>
</bindings>
<extensions>
<bindingElementExtensions>
<add name="cryptMessageEncoding" type="RobinLib.CryptEncodingBindingElementConfiguration,RobinLib,Version=1.0.0.0, Culture=neutral,PublicKeyToken=null"/>
</bindingElementExtensions>
</extensions>
</system.serviceModel>
</configuration>

托管服务的代码就轻便了好多,如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using Robin_Wcf_CustomMessageEncoder_SvcLib;
using System.ServiceModel.Channels;
using RobinLib; namespace Robin_Wcf_CustomMessageEncoder_Host
{
class Program
{
static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(Service1));
if (host.Description.Behaviors.Find<System.ServiceModel.Description.ServiceMetadataBehavior>() == null)
{
System.ServiceModel.Description.ServiceMetadataBehavior svcMetaBehavior = new System.ServiceModel.Description.ServiceMetadataBehavior();
svcMetaBehavior.HttpGetEnabled = true;
svcMetaBehavior.HttpGetUrl = new Uri("http://127.0.0.1:8001/Mex");
host.Description.Behaviors.Add(svcMetaBehavior);
}
host.Opened += new EventHandler(delegate(object obj, EventArgs e)
{
Console.WriteLine("服务已经启动!");
});
host.Open();
Console.Read();
}
}
}

WCF进阶:扩展bindingElementExtensions支持对称加密传输的更多相关文章

  1. ssl原理,非对称加密握手,对称加密传输

    SSL的基本思想是用非对称加密来建立链接(握手阶段),用对称加密来传输数据(传输阶段).这样既保证了密钥分发的安全,也保证了通信的效率. SSL握手,单方服务器认证(一般的浏览器上网) SSL握手,双 ...

  2. Vsftpd支持SSL加密传输

    ftp传输数据是明文,弄个抓包软件就可以通过数据包来分析到账号和密码,为了搭建一个安全性比较高ftp,可以结合SSL来解决问题   SSL(Secure Socket Layer)工作于传输层和应用程 ...

  3. 工作中拓展的加密解密传输方式. DES对称加密传输.

    系统间通过xml传输, 不能采用明文, 就加密传输. 秘钥(真正有效的是前8位)存储于配置中. public static string EncryptStr(this string content, ...

  4. 搭建支持SSL加密传输的vftpd

    让vsftpd支持SSL 必须让OPENSSL≥0.9.6版本还有就是本身vsftpd版本是否支持 查询vsftpd软件是否支持SSL        [root@localhost vsftpd]# ...

  5. [Node.js] 对称加密、公钥加密和RSA

    原文地址:http://www.moye.me/2015/06/14/cryptography_rsa/ 引子 对于加解密,我一直处于一种知其然不知其所以然的状态,项目核心部分并不倚重加解密算法时,可 ...

  6. HTTPS加密传输过程

    HTTPS加密传输过程 HTTPS全称Hyper Text Transfer Protocol over SecureSocket Layer,是以安全为目标的HTTP通道,在HTTP的基础上通过传输 ...

  7. linux下使用vsftp搭建FTP服务器:匿名登录,账号登录,SSL加密传输

    目录 一.关于FTP和VSFTP 二.ftp.sftp.vsftp.vsftpd的区别 三.项目一:搭建一台所有人都可以访问的通用FTP服务器 3.1 项目要求 3.2 项目思路分析 3.3 使用vs ...

  8. PHP的OpenSSL加密扩展学习(一):对称加密

    我们已经学过不少 PHP 中加密扩展相关的内容了.而今天开始,我们要学习的则是重点中的重点,那就是 OpenSSL 加密扩展的使用.为什么说它是重点中的重点呢?一是 OpenSSL 是目前 PHP 甚 ...

  9. SQL Server 2008, 2008 R2, 2012 and 2014 完全支持TLS1.2加密传输

    SQL Server 2008, 2008 R2, 2012 and 2014 完全支持TLS1.2加密传输 微软高兴地宣布所有主流SQL Server客户端驱动和SQL Server发行版已经支持T ...

随机推荐

  1. linux centos 装g++安装不了

    今天需要编译一个项目的时候在装g++都装不上, [root@master hadoop]# yum install g++ Loaded plugins: fastestmirror, refresh ...

  2. uoj118 【UR #8】赴京赶考

    题目 不难发现我们直接走过去就行了 考虑到第\(i\)行的构造方法就是把\(b\)数组作为模板,每个数和\(a_i\)异或一下就可以了 于是不难发现对于一段连续相等的\(a\),它们在矩阵上就形成了完 ...

  3. HDU 2167 状压dp方格取数

    题意:给出一个数表,规定取出一个数后周围的八个数都不可取,求可获得的最大数字和 思路:状态压缩dp,每一行的取数方法为状态,显然,由于取数规则的限制,可取的状态并不是 1<<size_co ...

  4. Jmeter----函数助手参数化

    要填写开始日期和结束日期和赋值的变量名

  5. opencv3.1.0 在控制台程序中报错:winnt.h(6464): error C2872: ACCESS_MASK: 不明确的

    在winnt.h里面有一个cv的命名空间,同样定义了一个ACCESS_MASK,跟opencv的cv::ACCESS_MASK发生了冲突!!! 该冲突在MFC中没有出现,在控制台程序中才会报错!对于o ...

  6. asprise-ocr-api-sample 高价收破解版64 32位

    asprise-ocr-api-sample验证码 高价收破解版64 32位 Reflector 8.5 打开自己的C#代码  完全100%的反编译了

  7. 关于TMDS

    https://en.wikipedia.org/wiki/Transition-minimized_differential_signaling TMDS,Transition Minimized ...

  8. 校园商铺-4店铺注册功能模块-4Dto之ShopExecution的实现

    1. DTO:添加店铺的返回类型 问题:为什么不直接用实体类Shop呢? 原因:在操作Shop的时候,必然会有一个状态.添加店铺,添加成功,还是添加失败? 如果添加失败,失败是一个什么状态,这些都是要 ...

  9. Could not open file ..\obj\sys.o: No such file or directory解决办法

    一.你的keil的安装路径以及系统用户名是否带中文字符以及一些特殊字符.二.环境变量的值存在中文或者特殊字符了,解决方法如下: 1.在C盘建立一个新的文件夹,命名为英文,如qcl2.右击"此 ...

  10. 用VC++MFC做文本编辑器(单文档模式)

    用VC++MFC做文本编辑器(单文档模式) 原来做过一个用对话框实现的文本编辑器,其实用MFC模板里面的单文档模板也可以做,甚至更加方便,适合入门级的爱好者试试,现介绍方法如下: < xmlna ...