参考链接: 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="data source=.;initial catalog=cesi;user id=sa;password=000;MultipleActiveResultSets=True;App=EntityFramework"";
- //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 项目是两个解决方案, 上述操作做完的时候, 运行可能会报错, 这是需要引用两个带来了文件, 就会解决
来源: https://www.cnblogs.com/lyq666666/p/10817727.html