在Winform开发框架中实现对数据库的加密支持
在很多情况下,我们需要对数据库进行加密,特别是Access数据库、Sqlite数据库,这些直接部署在客户端的数据,因为数据也是客户的资产,数据库总是存在很多相关的秘密或者重要的业务数据,所以一般来说,数据库是比较敏感的。由于我的Winform开发框架数据库访问模块中采用了EnterpriseLibrary模块,因此其实也可以使用其中的
Crytography Application Block进行加解密处理。
由于不想引入太多这些额外的模块,或者为了简化客户端的配置考虑,直接在EnterpriseLibrary模块内部对数据库连接字符串,增加密码部分,也是一个有效的方法,本文通过介绍这种方式,实现对加密
Access数据库连接字符串的
处理,并能顺利访问带密码的Access数据库。
1、数据库选择
如果要加密的是Access数据库,必须选择Access2007以上版本,这个版本的密码是经过128位的特殊处理,目前好像还是比较难破解,也好像没有找到合适的破解工具,如果是Access2000,那破解密码的工具真是多了去的了。
Access2007版本的数据库引擎,一般没有安装Office2007的电脑,是需要特别安装AccessDatabaseEngine这个驱动的。否则会提示“
The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine.”(未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序)的错误。到微软网站下载对应版本的驱动即可。
如果要加密的是Sqlite数据库,那么也是可以比较有效的,他的密码也是比较难于破解的。
上面两种客户端数据库,打开后先通过软件本身的功能进行加密,密码我们在开发初期就设定即可,客户一般不需要了解,他们或者其他人员复制出去,也无法单独使用,确保了数据库的安全性。
2、数据库加密处理
1)Access的数据库加密
如果是对Access的数据库加密,记住选择Access2007以上的格式,然后以独占方式打开Access文件,如下图所示。
然后在数据库工具选项里面,选择用密码进行加密,在弹出的对话框输入你的密码即可。
Office2007的密码强度还是不错的,至少我找了好几个工具,没能顺利破解出我的密码内容。
2)Sqlite数据库加密
Sqlite的数据库加密也很简单,我这里使用Sqlite Developer打开已有数据库,然后在数据库右键上选择Set Encryption Key,在弹出的对话框中输入密码即可。
我曾经专门针对Sqlite数据库机密机制做了一些了解,好像强度还是不错,而且据说性能损失是很少的。我在开发测试的时候,性能方面确实看不出太大的干扰。
3、连接字符串增加加密内容
由于我们希望数据库配置项尽可能简洁,因此可以不用在配置文件中指定访问密码,这样也避免了加密字符串的泄密问题,我们可以通过动态设置数据库访问对象
Database 的数据库访问密码属性进行内存上处理。如下代码所示是对Access数据库连接字符串进行增加加密字符串的操作。
#region 连接字符串加密
/// <summary> ///根据配置数据库配置名称生成Database对象/// </summary> /// <returns></returns> protected virtualDatabase CreateDatabase()
{
Database db= null;if (string.IsNullOrEmpty(dbConfigName))
{
db=DatabaseFactory.CreateDatabase();
}else{
db=DatabaseFactory.CreateDatabase(dbConfigName);
}
DbConnectionStringBuilder sb=db.DbProviderFactory.CreateConnectionStringBuilder();
sb.ConnectionString=GetConnectionString();
GenericDatabase newDb= newGenericDatabase(sb.ToString(), db.DbProviderFactory);
db=newDb;returndb;
}/// <summary> ///动态改变或者连接字符串/// </summary> /// <returns></returns> protected virtual stringGetConnectionString()
{string connectionString = "";
DatabaseSettings setting= ConfigurationManager.GetSection("dataConfiguration") asDatabaseSettings;if(setting != null)
{string defaultConnection =setting.DefaultDatabase;
connectionString=ConfigurationManager.ConnectionStrings[defaultConnection].ConnectionString;//尝试加密或者解密 if(!connectionString.EndsWith(";"))
{
connectionString+= ";";
}
connectionString+= string.Format("Jet OLEDB:Database Password=testpassword;");
}returnconnectionString;
}#endregion
通过在访问数据库的时候,动态增加加密的连接字符串,在系统的配置文件上,就和普通的没什么差别了,如下所示
<connectionStrings> <!--路径符号|DataDirectory|代表当前运行目录--> <addname="Access"providerName="System.Data.OleDb"connectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Database1.accdb;User ID=Admin;"/> <addname="sqlite"providerName="System.Data.SQLite"connectionString="Data Source=|DataDirectory|\ForumMis.db;Version=3;"/> </connectionStrings>
上面配置文件,Access数据库用的是2007格式的,所以用了Provider=Microsoft.ACE.OLEDB.12.0,如果是Access2000的话,那么就是Provider=Microsoft.Jet.OLEDB.4.0(基于安全原因,不用)。
Sqlite数据库的操作也类似, 它的加密字符串例子如下:
Data Source
=
c:\mydb.db
;
Version
=
3
;
Password
=
myPassword
;
当然密码可以使用自定义规则约定好的加密字符串,如下所示。
<!--路径符号|DataDirectory|代表当前运行目录--> <addname="sqlite"providerName="System.Data.SQLite"connectionString="Data Source=|DataDirectory|\HXHospitalDeploy.db;Version=3;Password=a9Da4YAgNxSeeYuXb5vvGw=="/>
然后在SQLite的访问基类BaseDALSQLite.cs 中,对自定义的密码进行解密处理即可。
#region 设置数据库的密码 /// <summary> ///根据配置数据库配置名称生成Database对象/// </summary> /// <returns></returns> protected overrideDatabase CreateDatabase()
{
Database db= null;if (string.IsNullOrEmpty(DbConfigName))
{
db=DatabaseFactory.CreateDatabase();
}else{
db=DatabaseFactory.CreateDatabase(DbConfigName);
}
DbConnectionStringBuilder sb=db.DbProviderFactory.CreateConnectionStringBuilder();
sb.ConnectionString=GetConnectionString(DbConfigName);
GenericDatabase newDb= newGenericDatabase(sb.ToString(), db.DbProviderFactory);
db=newDb;returndb;
}/// <summary> ///动态改变或者连接字符串/// </summary> /// <returns></returns> protected override string GetConnectionString(stringdbConfigName)
{string connectionString = "";
DatabaseSettings setting= ConfigurationManager.GetSection("dataConfiguration") asDatabaseSettings;if (setting != null)
{string connection = string.IsNullOrEmpty(dbConfigName) ?setting.DefaultDatabase : dbConfigName;
connectionString=ConfigurationManager.ConnectionStrings[connection].ConnectionString;#region 加密解密操作 //使用自定义加密 string password = GetSubValue(connectionString, "password");if (!string.IsNullOrEmpty(password))
{//尝试使用AES解密 string decryptStr =password;try{
decryptStr=EncodeHelper.AES_Decrypt(password);
}catch{
decryptStr=password; }
connectionString+= string.Format(";Password={0};", decryptStr);
}#endregion}returnconnectionString;
}#endregion
通过动态在连接字符串中增加加密字符串的方式,对于这些部署到客户端的数据库,第一个是提高安全性,用户分析不到那种加密类型;第二个是用户连接字符串不受干扰,可以正常阅读;第三是不用引入更多的模块和代码去实现。
以上只是我Winform开发框架用到的数据库字机密机制的一种,供大家参考和指正。