关于SSIS中解密数据库字符串的方法

     此文章适合于SSIS新手,我是个小白,在繁复查阅资料后仍无果到最后解决问题,走了很多弯路,现在讲其中一些关于SSIS的理解写出来,供大家参考,在正文之前,我就我自己的理解,阐明一些概念。

   什么是SSIS? 大数据中会涉及到一个概念, 叫ETL,中文就是数据的提取、加载、转换。SSIS是ETL常用工具中的一种,具体的这位仁兄的博客写的很详细http://www.cnblogs.com/qinpengming/archive/2011/12/06/2278299.html。我就不过多赘述了

   如果从SSIS包中需要读取SQL数据库中的连接信息,当然前提是这些信息是加密过的。需要一个媒介,来进行解密,再将解密后的连接字符串进行赋值,来让SSIS包正常执行封装测试。其实思路很明确,但是过程中总是会遇到一些莫名其妙的问题,尤其是在做升级的时候。

关于封装密碼明文的解決方案如下:

 

  1. 當把包在VS2015中打開之後,點擊SSIS菜單欄下的Package Configuration,查看鏈接管理配置信息。所以如下圖所示

 

 

 

    2.当我们选择用是脚本来解密数据库连接字符串的时候,就不再需要用配置包的SQL连接来获取了,所以需要删除相关的数据库配置数据,组态只保留除连接数据库配置以外的连接信息。因为组态读取某个数据库的配置信息,我们会把数据库里面的数据库连接加密,下面Connection Managers是识别不了加密的数据库连接,这样在VS2015上是可以正常跑,但是数据库调用会报错。所以我们要把组态里面的数据库连接删除。用脚本去数据库里面取读取数据库连接,并解密,把解密出来的数据库连接赋值给Connection Managers。

    3.添加一个腳本放在每個Package最前面,然后脚本中先写一个用windows身份连接的

       

 public static string GetConDb(string filter, string Dbname)
    {
        string Reaconn = "";
        string constr = "Data Source=.;Initial Catalog=IBBC;Integrated Security=SSPI;";
        string sqlstr = "SELECT * FROM IBBC.dbo.Table_1 where temp1='"+filter+"' and  temp2='"+Dbname+"'";
        SqlConnection con = new SqlConnection(constr);
        SqlCommand cmd = new SqlCommand(sqlstr, con);
        con.Open();
        try
        {
            SqlDataReader sdr = cmd.ExecuteReader();
            while (sdr.Read())
            {
                //此处获取对应的整个sql身份验证的连接字符串
                string bb = sdr[1].ToString();
                string[] connecstr = bb.Split();
                for (int i = 0; i < connecstr.Length; i++)
                {
                    //判断是否匹配到数组中的的密码
                    if (connecstr[i].Contains("Password"))
                    {
                        //获取带密码的字符串长度,比如:Password=Xeferfa0=长度为18
                        int GrossPwdlth = connecstr[i].Length;
                        //获取Password=后面的加密字符
                        string RevertoldPwd = connecstr[i].Substring(9, GrossPwdlth - 9);
                        //将获取到的密码密文进行解密
                        string newpwd = DecryptDES(RevertoldPwd, UUkey);
                        //将密文密码替换成明文密码
                        bb = bb.Replace(RevertoldPwd, newpwd);
                    }
                   
                }
                Reaconn = bb;
            }
            return Reaconn;
        }
        catch (Exception ex)
        {

            throw new Exception(ex.Message); ;
        }
        finally 
        {
            con.Close();        
        }      
    }

 

然后再用脚本组件中自带的DTs对象,将解密后的连接字符串赋值给配置数据源的名字 Dts.Connections[item].ConnectionString = Reaconn; , 当然中间采用什么加密方式,什么解密方式,各位都是大神,初级的也不是很难,我用的Des加密,如下。

    private static byte[] Keys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
    //密钥
    private static string UUkey = "********";
    /**/
    /**/
    /**/
    /// <summary>
    /// DES加密字符串
    /// </summary>
    /// <param name="encryptString">待加密的字符串</param>
    /// <param name="encryptKey">加密密钥,要求为8位</param>
    /// <returns>加密成功返回加密后的字符串,失败返回源串</returns>
    public static string EncryptDES(string encryptString, string encryptKey)
    {
        try
        {
            byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));
            byte[] rgbIV = Keys;
            byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);
            DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
            MemoryStream mStream = new MemoryStream();
            CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
            cStream.Write(inputByteArray, 0, inputByteArray.Length);
            cStream.FlushFinalBlock();
            return Convert.ToBase64String(mStream.ToArray());


        }
        catch
        {
            return encryptString;
        }
    }
    /**/
    /**/
    /**/
    /// <summary>
    /// DES解密字符串
    /// </summary>
    /// <param name="decryptString">待解密的字符串</param>
    /// <param name="decryptKey">解密密钥,要求为8位,和加密密钥相同</param>
    /// <returns>解密成功返回解密后的字符串,失败返源串</returns>
    public static string DecryptDES(string decryptString, string decryptKey)
    {
        try
        {
            byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey);
            byte[] rgbIV = Keys;
            byte[] inputByteArray = Convert.FromBase64String(decryptString);
            DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();
            MemoryStream mStream = new MemoryStream();
            CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
            cStream.Write(inputByteArray, 0, inputByteArray.Length);
            cStream.FlushFinalBlock();
            return Encoding.UTF8.GetString(mStream.ToArray());
        }
        catch
        {
            return decryptString;
        }

    }

 

4.到目前为止,所有的代码工作已经完成,剩下的就是配置问题,当我在VS2015环境中跑包全部通过之后,就只剩下SQL2012上进行封装跑包,在此期间,需要鼠标点击整个项目右键选中属性,此时在右侧属性栏位中,在ProtectionLevel 下选择EncryptSensitiveWithUserKey模式,之前没选择该模式,VS中关闭再打开包,连接数据源那里就会报红,VS和sql跑包都会失败,sql中提示未正确连接数据库,这里足足卡壳了两天,终于找到是这里保护级别的原因,具体内容见下表

 

不保存敏感数据 (DontSaveSensitive)

保存包时不保存包中敏感属性的值。 这种保护级别不进行加密,但它防止标记为敏感的属性随包一起保存,因此其他用户将无法使用这些敏感数据。 如果其他用户打开该包,敏感信息将被替换为空白,用户必须提供这些敏感信息。

当与 dtutil 实用工具 (dtutil.exe) 一起使用时,此保护级别对应的值为 0。

使用密码加密所有数据 (EncryptAllWithPassword)

使用密码加密整个包。 使用用户在创建包或导出包时提供的密码加密包。 若要在 SSIS 设计器中打开包或使用 dtexec 命令提示实用工具运行包,用户必须提供包密码。 如果没有密码,用户将无法访问或运行包。

当与 dtutil 实用工具一起使用时,此保护级别对应的值为 3。

使用用户密钥加密所有数据 (EncryptAllWithUserKey)

使用基于当前用户配置文件的密钥加密整个包。 只有创建包或导出包的用户才可以在 SSIS 设计器中打开包或使用 dtexec 命令提示实用工具运行包。

当与 dtutil 实用工具一起使用时,此保护级别对应的值为 4。

注意

对于使用用户密钥的保护级别,Integration Services 使用 DPAPI 标准。 有关 DPAPI 的详细信息,请参阅位于 http://msdn.microsoft.com/library 的 MSDN Library。

使用密码加密敏感数据 (EncryptSensitiveWithPassword)

使用密码只加密包中敏感属性的值。 DPAPI 用于此加密。 敏感数据作为包的一部分保存,但数据是使用当前用户在创建包或导出包时提供的密码加密的。 若要在 SSIS 设计器中打开包,用户必须提供包密码。 如果不提供该密码,则包虽然可以打开但其中不包含敏感数据,当前用户必须为敏感数据提供新值。 如果用户试图在不提供密码的情况下执行包,则包执行将会失败。 有关密码和命令行执行的详细信息,请参阅dtexec 实用工具

当与 dtutil 实用工具一起使用时,此保护级别对应的值为 2。

使用用户密钥加密敏感数据 (EncryptSensitiveWithUserKey)

使用基于当前用户配置文件的密钥只加密包中敏感属性的值。 只有使用同一配置文件的同一个用户才能加载此包。 如果其他用户打开该包,敏感信息将被替换为空白,当前用户必须为敏感数据提供新值。 如果用户试图执行该包,则包执行将会失败。 DPAPI 用于此加密。

当与 dtutil 实用工具一起使用时,此保护级别对应的值为 1。

注意

对于使用用户密钥的保护级别,Integration Services 使用 DPAPI 标准。 有关 DPAPI 的详细信息,请参阅位于 http://msdn.microsoft.com/library 的 MSDN Library。

依靠服务器存储进行加密 (ServerStorage)

使用 SQL Server 数据库角色保护整个包。 在将包保存到 SQL Server msdb 数据库后,支持此选项。 此外,SSISDB 目录使用 ServerStorage 保护级别。

在将包从 SQL Server Data Tools (SSDT) 保存到文件系统时,不支持此选项。

 

5.设置完后,请把packag关闭,在开启。看Connection Managers里面的数据库连接有沒有报红,如果沒有,就说明设置好了。

6.所有的准备工作都已完成,将包附加到SQL2012 中进行封装测试,如下图,包 执行封装测试成功

 

 

 作为资深小白,记录第一篇随笔,留下个脚印

 

-------市人皆大笑,举手揶揄之

 


 

posted @ 2016-09-21 18:03  郎中令  阅读(2189)  评论(4编辑  收藏  举报