• Nhibernate 3.0 cookbook学习笔记 创建一个加密类


    为数据库中的关键字段进行加密是必不可少的,特别是一些用户密码,银行卡账号等。现在我们来说一下如何在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; }      
    
            /// <summary>
            /// 加密,利用CryptoStream
            /// </summary>
            /// <param name="plainText"></param>
            /// <returns></returns>
            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;
            }
    
            /// <summary>
            /// 解密
            /// </summary>
            /// <param name="encryptedText"></param>
            /// <returns></returns>
            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<string, string> 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文件:

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
    assembly="EncryptedStringExample"
    namespace="EncryptedStringExample">
      <typedef
      name="encrypted"
      class="EncryptedStringExample.EncryptedString,
    EncryptedStringExample">
        <!--定义加密类-->
        <param name="encryptor">
          EncryptedStringExample.DESEncryptor,
          EncryptedStringExample
        </param>
        <!--设置密钥-->
        <param name="encryptionKey">12345678</param>
      </typedef>
      <class name="Account">
        <id name="Id">
          <generator class="guid.comb" />
        </id>
        <property name="Name" not-null="true" />
        <property name="EMail" not-null="true" />
        <!--要加密的字段,注意设置了type="encrypted"-->
        <property name="CardNumber" not-null="true" type="encrypted"
    />
        <property name="ExpirationMonth" not-null="true" />
        <property name="ExpirationYear" not-null="true" />
        <property name="ZipCode" not-null="true" />
      </class>
    </hibernate-mapping>

     在一个新建的控制台应用程序中,我们新建一个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<Account>().Take(1).SingleOrDefault();
            }

    在Main方法中增加两行代码:

      Account account = GetAccount(session);
      Console.WriteLine(account.CardNumber);

    我们可以看到控制台上显示出来的值为:

     可以看出解密正确。

     源码下载:点我。项目中的EncryptedStringExample与EncryptedStringTest

  • 相关阅读:
    Spring Boot 2.4版本前后的分组配置变化及对多环境配置结构的影响
    Spring Boot 2.4 对多环境配置的支持更改
    Spring Boot 的2020最后一击:2.4.1、2.3.7、2.2.12 发布
    苹果M1芯片各种不支持,但居然可以刷朋友圈!你会买单吗?
    老板居然让我在Java项目中“造假”
    Spring Cloud正式移除Hystrix、Zuul等Netflix OSS组件
    为了Java微信支付V3开发包,我找出了微信支付文档至少六个错误
    IdentityServer4系列 | 支持数据持久化
    IdentityServer4系列 | 混合模式
    Gitlab Runner的分布式缓存实战
  • 原文地址:https://www.cnblogs.com/Gyoung/p/2520669.html
Copyright © 2020-2023  润新知