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項目是兩個解決方案,上述操作做完的時候,運行可能會報錯,這是需要引用兩個帶來了文件,就會解決

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM