为数据库中的关键字段进行加密是必不可少的,特别是一些用户密码,银行卡账号等。现在我们来说一下如何在Nhibernate中创建一个加密类来为数据库中的关键字段加密。
让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:域名注册、网络空间、营销软件、网站建设、荔波网站维护、网站推广。1 创建一个接口:IEncryptor
public interface IEncryptor
{
string Encrypt(string plainText);
string Decrypt(string encryptedText);
string EncryptionKey { get; set; }
}
2 再创建一个继承它的子类:SymmetricEncryptorBase
public class SymmetricEncryptorBase : IEncryptor
{
private readonly SymmetricAlgorithm _cryptoProvider;
private byte[] _myBytes;
protected SymmetricEncryptorBase(
SymmetricAlgorithm cryptoProvider)
{
_cryptoProvider= cryptoProvider;
}
#region IEncryptor 成员
public string EncryptionKey { get; set; }
/// /// 加密,利用CryptoStream
/// /// /// public string Encrypt(string plainText)
{
var bytes = GetEncryptionKeyBytes();
using (var memoryStream = new MemoryStream())
{
ICryptoTransform encryptor= _cryptoProvider
.CreateEncryptor(bytes, bytes);
using (var cryptoStream = new CryptoStream(
memoryStream, encryptor, CryptoStreamMode.Write))
{
using (var writer = new StreamWriter(cryptoStream))
{
writer.Write(plainText);
writer.Flush();
cryptoStream.FlushFinalBlock();
return Convert.ToBase64String(
memoryStream.GetBuffer(),
0,
(int)memoryStream.Length);
}
}
}
}
//获取密钥 private byte[] GetEncryptionKeyBytes()
{
if (_myBytes == null)
_myBytes= Encoding.ASCII.GetBytes(EncryptionKey);
return _myBytes;
}
/// /// 解密
/// /// /// public string Decrypt(string encryptedText)
{
var bytes = GetEncryptionKeyBytes();
using (var memoryStream = new MemoryStream(
Convert.FromBase64String(encryptedText)))
{
ICryptoTransform decryptor= _cryptoProvider
.CreateDecryptor(bytes, bytes);
using (var cryptoStream = new CryptoStream(
memoryStream, decryptor, CryptoStreamMode.Read))
{
using (var reader = new StreamReader(cryptoStream))
{
return reader.ReadToEnd();
}
}
}
}
#endregion
}
3 再创建一个类:DESEncryptor
public class DESEncryptor : SymmetricEncryptorBase
{
public DESEncryptor()
:base(new DESCryptoServiceProvider())
{ }
}
4 再新建一个类:EncryptedString,通过这个类来调用前面的DESEncryptor来加密解密字符串
public class EncryptedString : IUserType, IParameterizedType
{
private IEncryptor _encryptor;
public object NullSafeGet( IDataReader rs, string[] names, object owner)
{
//treat for the posibility of null values object passwordString =
NHibernateUtil.String.NullSafeGet(rs, names[0]);
if (passwordString != null)
{
return _encryptor.Decrypt((string)passwordString);
}
return null;
}
public void NullSafeSet(IDbCommand cmd,object value,int index)
{
if (value == null)
{
NHibernateUtil.String.NullSafeSet(cmd,null, index);
return;
}
string encryptedValue = _encryptor.Encrypt((string)value);
NHibernateUtil.String.NullSafeSet(
cmd, encryptedValue, index);
}
public object DeepCopy(object value)
{
return value == null ? null :
string.Copy((string)value);
}
public object Replace(object original,
object target, object owner)
{
return original;
}
public object Assemble(object cached, object owner)
{
return DeepCopy(cached);
}
public object Disassemble(object value)
{
return DeepCopy(value);
}
public SqlType[] SqlTypes
{
get
{
return new[] { new SqlType(DbType.String) };
}
}
public Type ReturnedType
{
get { return typeof(string); }
}
public bool IsMutable
{
get { return false; }
}
public new bool Equals(object x, object y)
{
if (ReferenceEquals(x, y))
{
return true;
}
if (x == null || y == null)
{
return false;
}
return x.Equals(y);
}
public int GetHashCode(object x)
{
if (x == null)
{
throw new ArgumentNullException("x");
}
return x.GetHashCode();
}
public void SetParameterValues(
IDictionary parameters)
{
if (parameters != null)
{
var encryptorTypeName = parameters["encryptor"];
_encryptor= !string.IsNullOrEmpty(encryptorTypeName)
? (IEncryptor)Instantiate(encryptorTypeName)
:new DESEncryptor();
var encryptionKey = parameters["encryptionKey"];
if (!string.IsNullOrEmpty(encryptionKey))
_encryptor.EncryptionKey= encryptionKey;
}
else
{
_encryptor= new DESEncryptor();
}
}
private static object Instantiate(string typeName)
{
var type = Type.GetType(typeName);
return Activator.CreateInstance(type);
}
}
OK.这个加密类到此就完成了。现在我们来创建一个Account对象来测试。
public class Account
{
public virtual Guid Id { get; set; }
public virtual string EMail { get; set; }
public virtual string Name { get; set; }
public virtual string CardNumber { get; set; }
public virtual int ExpirationMonth { get; set; }
public virtual int ExpirationYear { get; set; }
public virtual string ZipCode { get; set; }
}
重要的是定义相应的Account.hbm.xml文件:
EncryptedStringExample.DESEncryptor,
EncryptedStringExample
12345678
在一个新建的控制台应用程序中,我们新建一个Account对象来测试一下:
private static void AddAccount(NHibernate.ISession session)
{
session.Save(new Account() {
CardNumber="45678",
EMail="bb@qq.com",
ExpirationMonth=12,
ExpirationYear=2012,
Name="gyoung",
ZipCode="55555"
});
}
加密的字段为:CardNumber.打开数据库,看到存储在其中的字段已经被加密了.
现在我们从数据库中取出该字段看看。因为只有一条记录,我就只取第一条了。
private static Account GetAccount(NHibernate.ISession session)
{
return session.QueryOver().Take(1).SingleOrDefault();
}
在Main方法中增加两行代码:
Account account = GetAccount(session);
Console.WriteLine(account.CardNumber);
我们可以看到控制台上显示出来的值为:
可以看出解密正确。
源码下载:点我。项目中的EncryptedStringExample与EncryptedStringTest