ASP.NET项目发布后,web.config中的文件会包含一些敏感信息,比如数据库连接字符串等,这就需要对其进行加密处理,以保证数据的安全性。对于连接字符串的加密有很多种方法。比如借助企业库的加密、自己手写加密与解密方法、利用现成的工具ASP.NET IIS 注册工具 (Aspnet_regiis.exe)等。
这里不对三种方法的优劣具体讨论,只说一下个人对于使用的感受。
对于第一种企业库的加密方法,由于本人之前并没有具体的了解,所以没有花精力去研究。
对于第二种自己手写加密与解密,因为之前的项目web.config是采用明码的形式发布在客户的服务器上的,后来由于安全性要求,要对数据库连接字符串进行加密。我一开始是采用这种方式,自己写了对称加密的算法,并做了一个小工具,专门提供给用户用来修改数据库连接配置。加密、解密与修改配置,经测试后,一切OK。可是等到要在项目中应用其解析的方法时才发现,不止是当前项目,连引用的dll也要重新使用该算法进行解析,甚至之前使用微软企业库的一些内容,都要加上这些对加密算法的解析,这是一个相当繁琐的事情。因为dll是之前已经封装好的工具。于是遂探索其它方法以最小程度地修改已经正在运行的程序的源代码。
这里要重点说一下第三种方法,即采用ASP.NET IIS 注册工具 (Aspnet_regiis.exe)对web.config实行本地加密,在应用程序项目中无需对该文件进行解密操作,.NET框架会自动替我们完成。看到这里,自然让我很感兴趣,因为这样的话就实现了我的目标:对源代码进行最小的改动。下面具体进行说明:
加密方法
打开SDK命令提示,输入命令:aspnet_regiis –pef "要加密的配置节" "物理目录"
解密方法
打开SDK命令提示,输入命令:aspnet_regiis –pdf "要解密的配置节" "物理目录"
其中pef和pdf,个人猜测,其中的e和d分别为encode和decode。
注意:其中后两项的引号可以去掉。
加密和解密的方法就是这么简单,怎么样?但是,这里的加密和解密利用了计算机本身的信息生成RSA算法的密钥,于是,只能在web程序所在的服务器上面进行加密命令的执行。
可以采用批处理的方式执行命令,将加密命令写成一个批处理文件,双击,即可实现web.config的加密,如下面的形式
@C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis -pdf connectionStrings D:\001
@pause
上面的命令中包含两个地址:.net所在的地址和web.config所在的地址,于是由不熟悉的人员进行维护的时候,就不能实现傻瓜式维护。这可肿么办倪?我们可以将其做成一个客户端小工具中,用C#程序调用批处理命令,从而实现,两个地址均可配置或者由用户选择。
#region 执行批处理命令 ////// 执行cmd命令,对配置文件进行加密和解密 /// 这里用aspnet_regiis对配置文件进行加密,程序可以在不解密的情况下进行正常的访问。 /// 但这里的加密与具体的服务器有关,本地加密的内容更换机器后不可识别 /// 命令格式为:aspnet_regiis -pef 配置节 物理路径 /// 如:aspnet_regiis -pef connectionStrings C:\test123 /// /// private void ExcuteCmd(string CodeType) { //读取当前.Net所在的路径 //_netPath = System.Configuration.ConfigurationManager.AppSettings["netPath"]; //批处理命令 string MyDosComLine1, MyDosComLine2 = string.Empty; string path = _path.Substring(3, _path.Length - 14); //去掉前面的磁盘盘符和最后的文件名 分别为D:\\和\web.config MyDosComLine1 = @"cd\";//返回根目录命令 if (CodeType == "加密") MyDosComLine2 = "C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\aspnet_regiis -pef connectionStrings " + path; else if (CodeType == "解密") MyDosComLine2 = "C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\aspnet_regiis -pdf connectionStrings " + path; Process myProcess = new Process(); myProcess.StartInfo.FileName = "cmd.exe ";//打开DOS控制平台 myProcess.StartInfo.UseShellExecute = false; myProcess.StartInfo.CreateNoWindow = true;//是否显示DOS窗口,true代表隐藏; myProcess.StartInfo.RedirectStandardInput = true; myProcess.StartInfo.RedirectStandardOutput = true; myProcess.StartInfo.RedirectStandardError = true; myProcess.Start(); StreamWriter sIn = myProcess.StandardInput;//标准输入流 sIn.AutoFlush = true; StreamReader sOut = myProcess.StandardOutput;//标准输入流 StreamReader sErr = myProcess.StandardError;//标准错误流 sIn.Write(MyDosComLine1 + System.Environment.NewLine);//第一条DOS命令 sIn.Write(MyDosComLine2 + System.Environment.NewLine);//第二条DOS命令 sIn.Write("exit" + System.Environment.NewLine);//第四条DOS命令,退出DOS窗口 string s = sOut.ReadToEnd();//读取执行DOS命令后输出信息 string er = sErr.ReadToEnd();//读取执行DOS命令后错误信息 if (myProcess.HasExited == false) { myProcess.Kill(); } else { //MessageBox.Show(s); } sIn.Close(); sOut.Close(); sErr.Close(); myProcess.Close(); } #endregion
这样在工具中的其他地方就可以通过
ExcuteCmd("加密");
ExcuteCmd("解密");
来进行相应的操作。至于对于数据库连接字符串进行修改部分的代码,不在这里的范畴,不进行列出。注意事项:
- a、发布时,不能对配置文件加密,必须明码发布
- b、在部署应用程序后,再对配置文件进行加密
- c、在服务器的 C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys 目录下,找到新生成的加密文件(根据日期可以找到),设置其对于用户network和network service的读取权限。该权限仅在首次部署时进行设置,之后每次更新程序和重新加密均无需重复设置。