微软企业库5.0 学习之路——第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—下篇
在上一篇文章中, 我介绍了企业库Cryptographer模块的一些重要类,同时介绍了企业库Cryptographer模块为我们提供的扩展接口,今天我就要根据这些 接口来进行扩展开发,实现2个加密解密方法(离散加密和对称性加密),分别实现自接口IHashProvider和接口 ISymmetricCryptoProvider。
首先来看下离散加密——CustomHashCryptography,具体代码如下:
using System;
using System.Collections.Generic;
//构造函数中接受参数的类型NameValueCollection所在命名空间
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Security.Cryptography; using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;//用于企业库配置工具绑定
using Microsoft.Practices.EnterpriseLibrary.Security.Cryptography;
using Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.Configuration; namespace EntLibStudy.Helper
{
[ConfigurationElementType(typeof(CustomHashProviderData))]
public class CustomHashCryptography : IHashProvider
{
/// <summary>
/// 构造函数,此处不可省略,否则会导致异常
/// </summary>
/// <param name="attributes">配置文件中所配置的参数</param>
public CustomHashCryptography(NameValueCollection attributes)
{
}
/// <summary>
/// 比较数据和已加密数据是否相等
/// </summary>
/// <param name="plaintext">未加密数据</param>
/// <param name="hashedtext">已加密数据</param>
/// <returns>是否相等</returns>
public bool CompareHash(byte[] plaintext, byte[] hashedtext)
{
var tmpHashText = CreateHash(plaintext);
if (tmpHashText == null || hashedtext == null)
return false;
if (tmpHashText.Length != hashedtext.Length)
return false;
for (int i = ; i < tmpHashText.Length; i++)
{
if (tmpHashText[i] != hashedtext[i])
return false;
}
return true;
}
/// <summary>
/// 创建加密
/// </summary>
/// <param name="plaintext">待加密数据</param>
/// <returns>加密后数据</returns>
public byte[] CreateHash(byte[] plaintext)
{
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
return md5.ComputeHash(plaintext);
}
}
}
这段代码主要就是实现一个离散加密,不过还是有几点需要注意:
1、在实现接口IHashProvider的基础上,为了能让这个自定义加密可以在企业库的配置工具里调用到需要为类加上一个特性: [ConfigurationElementType(typeof(CustomHashProviderData))],这个特性所在的命名空间为:using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;。
2、这个自定义加密必须包含一个构造函数,其参数的类型是NameValueCollection,这个参数是从配置文件中获取指定的配置属性,见下图:
注意:这个NameValueCollection类型,需要引用命名空间:using System.Collections.Specialized;
如果没有这个构造函数,将会引发异常:
Type does not provide a constructor taking a single parameter type of NameValueCollection
3、方法CompareHash、CreateHash,接收和返回的类型都是字节数组。
接下来看下对称加密CustomSymmetricCryptography ,具体代码如下:
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO; using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Security.Cryptography;
using Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.Configuration; namespace EntLibStudy.Helper
{
[ConfigurationElementType(typeof(CustomSymmetricCryptoProviderData))]
public class CustomSymmetricCryptography : ISymmetricCryptoProvider
{
private string encryptKey="";
public CustomSymmetricCryptography(NameValueCollection attributes)
{
//从配置文件中获取key,如不存在则指定默认key
encryptKey = String.IsNullOrEmpty(attributes["key"]) ? "kyo-yo" : attributes["key"];
} //默认密钥向量
private static byte[] Keys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; /// <summary>
/// 加密
/// </summary>
/// <param name="ciphertext">待加密数据</param>
/// <returns>加密后数据</returns>
public byte[] Decrypt(byte[] ciphertext)
{
if (encryptKey.Length > )
{
encryptKey = encryptKey.Substring(, );
}
encryptKey = encryptKey.PadRight(, ' ');
byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey);
byte[] rgbIV = Keys;
byte[] inputByteArray = ciphertext;
DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider(); MemoryStream mStream = new MemoryStream();
CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
cStream.Write(inputByteArray, , inputByteArray.Length);
cStream.FlushFinalBlock();
return mStream.ToArray();
} /// <summary>
/// 解密
/// </summary>
/// <param name="plaintext">加密数据</param>
/// <returns>解密后数据</returns>
public byte[] Encrypt(byte[] plaintext)
{
if (encryptKey.Length > )
{
encryptKey = encryptKey.Substring(, );
}
encryptKey = encryptKey.PadRight(, ' ');
byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(, ));
byte[] rgbIV = Keys;
byte[] inputByteArray = plaintext;
DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
MemoryStream mStream = new MemoryStream();
CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
cStream.Write(inputByteArray, , inputByteArray.Length);
cStream.FlushFinalBlock();
return mStream.ToArray();
}
}
}
这个对称性加密的注意点基本和离散加密一样,但是这边的对称加密我引入了一个加密key,这个key是从配置文件中获取的。
第三点:在项目中应用自定义接口
在上面已经扩展好了2个加密方式,现在就要在实际的项目中运用这2个加密方式,首先打开企业库的配置工具,添加Cryptographer模块,然 后在Hash Providers和ISymmetric Cryptograhpy Providers下分别添加刚才定义好的2个加密方式。
注意:添加的自定义加密方式必须放在项目的根目录下,如果放在项目下的文件夹下,如:Helper\Extension下,从企业库的配置文件中将无法找到自定义的加密方式,见下图:
在添加完配置后就可以在web.config看到以下配置信息:
<securityCryptographyConfiguration>
<hashProviders>
<add type="EntLibStudy.Helper.CustomHashCryptography, EntLibStudy.Helper, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
name="CustomHashCryptography" />
</hashProviders>
<symmetricCryptoProviders>
<add key="kyo-yo" type="EntLibStudy.Helper.CustomSymmetricCryptography, EntLibStudy.Helper, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
name="CustomSymmetricCryptography" />
</symmetricCryptoProviders>
</securityCryptographyConfiguration>
配置完后,我又在Helper.Utils类中添加了几个加密解密方法的封装,用于表示层调用(主要是根据配置实例名和待加密数据获取加密数据),代码如下:
/// <summary>
/// 根据配置进行加密
/// </summary>
/// <param name="instance">配置实例名</param>
/// <param name="encryptString">待加密字符串</param>
/// <returns>加密后字符串</returns>
public static string Encode(string instance, string encryptString)
{
return Cryptographer.EncryptSymmetric(instance, encryptString);
}
/// <summary>
/// 根据配置进行解密
/// </summary>
/// <param name="instance">配置实例名</param>
/// <param name="decryptString">待解密字符串</param>
/// <returns>解密后字符串</returns>
public static string Decode(string instance, string decryptString)
{
return Cryptographer.DecryptSymmetric(instance, decryptString);
}
/// <summary>
/// 根据配置进行离散加密
/// </summary>
/// <param name="instance">配置实例名</param>
/// <param name="plaintString">待加密字符串</param>
/// <returns>解密后字符串</returns>
public static string CreateHash(string instance, string plaintString)
{
return Cryptographer.CreateHash(instance, plaintString);
}
/// <summary>
/// 比较离散值是否相等
/// </summary>
/// <param name="instance">配置实例名</param>
/// <param name="plaintString">未加密字符串</param>
/// <param name="hashedString">已加密字符串</param>
/// <returns>是否相等</returns>
public static bool CompareHash(string instance,string plaintString, string hashedString)
{
return Cryptographer.CompareHash(instance, plaintString, hashedString);
}
接下来就是主要的项目应用了,在以前的代码中,例如学员的密码我是以明文的形式保存进数据库的,这显示是很不安全的,现在我就要替换这块代码,通过调用Utils.CreateHash方法加密录入的密码:
/// <summary>
/// 获取已验证的学员对象
/// </summary>
/// <param name="student">学员对象</param>
/// <returns>是否验证成功</returns>
private bool GetValidatedStudent(ref Model.Student student)
{
if (student == null)
{
student = new Model.Student();
}
student.ClassId = Convert.ToInt32(ddlClass.SelectedValue);
student.Sid = txtSid.Text.Trim();
student.Password = Helper.Utils.CreateHash("CustomHashCryptography", txtPwd.Text.Trim());
student.Name = txtName.Text.Trim();
student.Sex = Convert.ToInt32(rblSex.SelectedValue);
student.Birthday = DateTime.Parse(txtBirthday.Text.Trim()); return student.IsValid();
}
以上就是本文的主要内容,本文主要介绍了:
1、如何通过企业库Cryptographer模块给出的接口进行扩展加密方法,以及扩展时需要注意的问题
2、在项目中使用已经扩展好的加密方法。
本文内容比较简单,如发现问题欢迎指出,谢谢大家!
源代码下载:点我下载
注意:
1、MSSQL数据库在DataBase目录下(需要自行附加数据库),SQLite数据库在Web目录的App_Data下,由于考虑到项目的大小,所以每个项目的BIN目录都已经删除,如出现无法生成项目请自行添加相关企业库的DLL。
2、由于微软企业库5.0 学习之路这个系列我是准备以一个小型项目的形式介绍企业库的各模块,所以源代码会根据系列文章的更新而更新,所以源代码不能保证与文章中所贴代码相同。
3、项目开发环境为:VS2010+SQL2005。
4、管理员帐户:admin
密码:admin
微软企业库5.0 学习之路——第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—下篇的更多相关文章
- 微软企业库5.0 学习之路——第八步、使用Configuration Setting模块等多种方式分类管理企业库配置信息
在介绍完企业库几个常用模块后,我今天要对企业库的配置文件进行处理,缘由是我打开web.config想进行一些配置的时候发现web.config已经变的异常的臃肿(大量的企业库配置信息充斥其中),所以决 ...
- 微软企业库5.0 学习之路——第六步、使用Validation模块进行服务器端数据验证
前端时间花了1个多星期的时间写了使用jQuery.Validate进行客户端验证,但是那仅仅是客户端的验证,在开发项目的过程中,客户端的信息永远是不可信的,所以我们还需要在服务器端进行服务器端的验证已 ...
- 微软企业库5.0 学习之路——第四步、使用缓存提高网站的性能(EntLib Caching)
首先先补习下企业库的Caching Application Block的相关知识: 1.四大缓存方式,在Caching Application Block中,主要提供以下四种保存缓存数据的途径,分别是 ...
- 微软企业库5.0 学习之路——第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——下篇
一.独立验证器 我上篇中我将AndCompositeValidator和OrCompositeValidator归为独立验证器,这2个验证器主要是为了第一类验证服务,可以进行多种验证组合在一起进行复杂 ...
- 微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)
今天继续介绍Unity,在上一篇的文章中,我介绍了使用UnityContainer来注册对象之间的关系.注册已存在的对象之间的关系,同时着重介绍 了Unity内置的各种生命周期管理器的使用方法,今天则 ...
- [EntLib]微软企业库5.0 学习之路——第一步、基本入门
话说在大学的时候帮老师做项目的时候就已经接触过企业库了但是当初一直没明白为什么要用这个,只觉得好麻烦啊,竟然有那么多的乱七八糟的配置(原来我不知道有配置工具可以进行配置,请原谅我的小白). 直到去年在 ...
- 微软企业库5.0 学习之路——第二步、使用VS2010+Data Access模块建立多数据库项目
现在我就开始进入学习之路的第二步——Data Access模块,这个模块是企业库中被使用频率最高的模块,它很好的封装了数据库操作应用,为我们进行多数据库系统开发提供了便利,只需更改配置文件就 可以很快 ...
- 微软企业库5.0 学习之路——第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录
在前面的Part3中, 我介绍Policy Injection模块中内置的Call Handler的使用方法,今天则继续介绍Call Handler——Custom Call Handler,通过建立 ...
- 微软企业库5.0 学习之路——扩展学习篇、库中的依赖关系注入(重构 Microsoft Enterprise Library)[转]
这篇文章是我在patterns & practices看到的一篇有关EntLib5.0的文章,主要介绍了EntLib5.0的这次的架构变化由来,觉得很不错,大家可以看一下! 在过去几年中,依赖 ...
随机推荐
- zigbee ---- 各种ID的作用
EPAN ID的作用:
- git如何删除本地所有未提交的更改
stash很好用,至少不会影响 .gitignore 里面的不跟踪的文件: git add . && git stash && git stash drop ===== ...
- Linux和windows下检查jsp后门文件的方法
Linux下: find . -name "*.jsp" | xargs egrep -liw "createNewFile| File\(| File |applica ...
- websocket连接相关的几个问题
https://blog.csdn.net/shangmingtao/article/details/75810099 https://blog.csdn.net/keketrtr/article/d ...
- bzoj 4034: [HAOI2015]树上操作——树链剖分
Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中 ...
- 【BZOJ】4530: [Bjoi2014]大融合
[题意]给定n个点的树,从无到有加边,过程中动态询问当前图某条边两端连通点数的乘积,n<=10^5. [算法]线段树合并+并查集 (||LCT(LCT维护子树信息 LCT维护子树信息(+启发式合 ...
- WP8.1 Windows Phone 8.1开发:何如定义Pivot头部样式、定义Pivot头部颜色
Windows Phone 8.1 ,如何自定义Pivot头部样式?用Pivot控件完成这样的效果. 网上找了好久,只找到了windows phone 8的解决方案. 终于一个大神给支了招,我觉得我有 ...
- 你自认为理解了JavaScript?【转】
第一题 if (!("a" in window)) { var a = 1; } alert(a); 第二题 var a = 1, b = function a(x) { x &a ...
- bootstrap-table组合表头
1.效果图 2.html代码 <table id="table"></table> 3.javascript代码 $("#table") ...
- Python3 Socket和SocketServer 网络编程
socket只能实现同时一个服务和一个客户端实现交互,socketserver可以实现多个客户端同时和服务端交互 1.利用Socket编写简单的同一个端口容许多次会话的小案例: 服务端: #!/usr ...