zoukankan      html  css  js  c++  java
  • 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项目是两个解决方案,上述操作做完的时候,运行可能会报错,这是需要引用两个带来了文件,就会解决

  • 相关阅读:
    linux基础练习题(3)
    linux基础练习题(2)
    linux基础练习题(1)
    编辑器 vim
    Linux 命令总结
    Sublime Text 3 快捷键总结(拿走)
    Linux 主要目录速查表
    javaScript中的querySelector()与querySelectorAll()的区别
    javaScript定时器
    js基本类型和字符串的具体应用
  • 原文地址:https://www.cnblogs.com/lyq666666/p/10817727.html
Copyright © 2011-2022 走看看