EF连接字符串加密及封装

参考链接: https://blog.csdn.net/shujudeliu/article/details/80692403

我们做如下准备工作:

1.创建一个名称为“Web_Ado”的解决方案

2.在解决方案中添加一个名称为“EFModel”类库子项目、一个名称为“EFModel”类库子项目

3.在“Test.DB”子项目中添加“ADO.NET实体数据模型”,命名为“Model2.edmx”,然后在弹出的“实体模型向导”中,选择从数据库生成,新建连接→连接属性,输入数据库服务器的ip、用户名、密码、指定数据库,然后选择“是,在连接字符串中包含敏感数据”,将App.Config中的实体链接另存为Model2Container,然后勾选数据库中的表

打开Model2.Container.cs

可以看到如下代码:

public partial class Model2Container : DbContext
    {
        public Model2Container()
            : base("name=Model2Container")
        {
        }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }
    
        public virtual DbSet<Products> Products { get; set; }
        public virtual DbSet<TreeMenu> TreeMenu { get; set; }
        public virtual DbSet<Users> Users { get; set; }
    }

这里的TestEntities实体对象继承自DbContext对象,构造函数继承自父类DbContext,如果VS里安装了.net reflector插件F12转到定义就可以看到DbContext类里读取的是App.Config中的<connectionStrings>节的配置。

我们考虑的连接字符串加密是:使用对称加密算法把连接字符串进行加密后放入App.Config配置文件中,创建数据库实体对象时先对连接字符串解密,然后使用解密后的连接字符串进行创建。

由于创建数据库实体对象TestEntities时向导自动创建无参的构造函数调用的实际是父类DbContext中的构造方法,我们没办法对父类DbContext做修改,那么就只能对TestEntities类的构造函数进行重载,但是该类是是通过向导自动生成的,直接在类里修改明显不合适(重新自动生成时我们做的修改会被覆盖掉),但是可以看到TestEntities类修饰符是带有partial关键字的,即该类是一个分部类,我们可以新建一个同名分部类来对该类进行扩展:

创建同名类Model2db.cs

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EFModel
{
   
    public partial class Model2Container : DbContext
    {
        public Model2Container(string connectionStr)
            : base(connectionStr)
        {
            
            
        }
    }


}

该类包含一个有参构造函数,在使用该构造函数创建EF实体对象时不会直接从App.Config中读取,而是由我们指定传入。

还需要我们在创建一个DBContentxHelper帮助类,用于解密/加密获取的webconfig链接字符串的文件

 

public static class Model2Helper
    {
        public static Model2Container GetDBContext()
        {
            string cnnstr = ConfigurationManager.ConnectionStrings["Model2Container"].ConnectionString;//获取webconfig中链接字符串
            string cnstr = new SymmetricMethod().Decrypto(cnnstr);//解密
            return new Model2Container(cnstr);
           
        }
        
    }

二、EF连接字符串加密——加密与封装

我们使用上篇.net reactor的使用中创建的项目来加密解密连接字符串。但是怎么达到封装的目的呢?

为了达到封装的目的,加密类方法的修饰符要做下调整,由public调整为internal(若是两个解决方案需要用public),即限制本项目内使用:  

创建一个SymmetricMethod类,用于做加密和解密:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace EFModel
{

   

        //密码生成:https://suijimimashengcheng.51240.com/   
 //internal 
        public class SymmetricMethod
        {
            private SymmetricAlgorithm mobjCryptoService;
            private string Key;
            /// <summary>     
            /// 对称加密类的构造函数  internal    
            /// </summary>     
            public SymmetricMethod()
            {
                mobjCryptoService = new RijndaelManaged();
                Key = "FefZ$@pAedzg#HjT!QcM7JQqwOcAkCm7x2pZjBUMSocM9v6#%AP9HZg7OZ^ogG!x";
            }
            /// <summary>     
            /// 获得密钥     
            /// </summary>     
            /// <returns>密钥</returns>     
            private byte[] GetLegalKey()
            {
                string sTemp = Key;
                mobjCryptoService.GenerateKey();
                byte[] bytTemp = mobjCryptoService.Key;
                int KeyLength = bytTemp.Length;
                if (sTemp.Length > KeyLength)
                    sTemp = sTemp.Substring(0, KeyLength);
                else if (sTemp.Length < KeyLength)
                    sTemp = sTemp.PadRight(KeyLength, ' ');
                return ASCIIEncoding.ASCII.GetBytes(sTemp);
            }
            /// <summary>     
            /// 获得初始向量IV     
            /// </summary>     
            /// <returns>初试向量IV</returns>     
            private byte[] GetLegalIV()
            {
                string sTemp = "XUYXqW8QF2fqyytf0ZwU6Vv1cbNI3qU!zVzohQ0ptAug#&uJ3b^rEKkrckH1LE3i";
                mobjCryptoService.GenerateIV();
                byte[] bytTemp = mobjCryptoService.IV;
                int IVLength = bytTemp.Length;
                if (sTemp.Length > IVLength)
                    sTemp = sTemp.Substring(0, IVLength);
                else if (sTemp.Length < IVLength)
                    sTemp = sTemp.PadRight(IVLength, ' ');
                return ASCIIEncoding.ASCII.GetBytes(sTemp);
            }
            /// <summary>     
            /// 加密方法     internal 
            /// </summary>     
            /// <param name="Source">待加密的串</param>     
            /// <returns>经过加密的串</returns>     
            public string Encrypto(string Source)
            {
                byte[] bytIn = UTF8Encoding.UTF8.GetBytes(Source);
                MemoryStream ms = new MemoryStream();
                mobjCryptoService.Key = GetLegalKey();
                mobjCryptoService.IV = GetLegalIV();
                ICryptoTransform encrypto = mobjCryptoService.CreateEncryptor();
                CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Write);
                cs.Write(bytIn, 0, bytIn.Length);
                cs.FlushFinalBlock();
                ms.Close();
                byte[] bytOut = ms.ToArray();
                return Convert.ToBase64String(bytOut);
            }
            /// <summary>     
            /// 解密方法     internal 
            /// </summary>     
            /// <param name="Source">待解密的串</param>     
            /// <returns>经过解密的串</returns>     
            public string Decrypto(string Source)
            {
                byte[] bytIn = Convert.FromBase64String(Source);
                MemoryStream ms = new MemoryStream(bytIn, 0, bytIn.Length);
                mobjCryptoService.Key = GetLegalKey();
                mobjCryptoService.IV = GetLegalIV();
                ICryptoTransform encrypto = mobjCryptoService.CreateDecryptor();
                CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Read);
                StreamReader sr = new StreamReader(cs);
                return sr.ReadToEnd();
            }
        }
    

}

接下来在控制器中测试:

//EFModel.Model2db db = new EFModel.Model2db("");
EFModel.Model2Container db =EFModel.Model2Helper.GetDBContext();
public ActionResult Index()
{
//string sss="metadata=res://*/Model2.csdl|res://*/Model2.ssdl|res://*/Model2.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.;initial catalog=cesi;user id=sa;password=000;MultipleActiveResultSets=True;App=EntityFramework&quot;";
//string EnSSS = new EFModel.SymmetricMethod().Encrypto(sss);
var p = db.Products.FirstOrDefault();
string name= p.ProductName;
name = name + "";
return View(p);
}

看下webconfig中的链接

     <connectionStrings>    
 <add name="Model2Container" connectionString="tnyrLxN6i4y1GZ5JiS8XpL9OmJf9+4yk7V/XcmK9O0FEZUVMXqR+GphenP1Ot9JekUlShNbWo7HyJvbMnzhi9kStMdBzLFMENiuoJj3uCWAq0UWE6S5/dPHqFR35G/kWflvfZ6aBtdyB74SnvOEwRPQ6FpbHQD/c23zTOIfZwQd4tMVF8/mQ9ciH/ZEEMMaeAPARsstPvRdRMhYlrRp4gt4gQxD//l/sFtorhcPdUxalU/myKCrU/zaUL+3+4acIP3JtGZOF0SkK01cABUXUXjF6fb9MgWn6Jbo/rjavgiUgGX+UGZke1aPyyymNe2+6" providerName="System.Data.EntityClient" />
     </connectionStrings>

注意: 如果是实体数据模型跟MVC项目是两个解决方案,上述操作做完的时候,运行可能会报错,这是需要引用两个带来了文件,就会解决

 

posted @ 2019-05-06 09:08  大黄人  阅读(1871)  评论(2编辑  收藏  举报