一 简介当创建ASPNET 应用程序时开发者通常都把敏感的配置信息存储在nfig文件中最典型的示例就是数据库连接字符串但是包括在nfig文件中的其它敏感信息还包括SMTP服务器连接信息和用户凭证数据等等 尽管默认情况下可以配置ASPNET以拒绝所有对扩展名nfig的文件资源的HTTP请求但是如果一个黑客能够存取你的web服务器的文件系统的话那么nfig中的敏感信息仍然能够被窃取例如也许你不小心允许匿名FTP存取你的网站这样以来就允许一个黑客简单地通过FTP协议下载你的nfig文件
幸好通过允许加密nfig文件中选择的部分例如<connectionStrings>节或你的应用程序使用的一些定制config节ASPNET 有助于缓解这个问题配置部分能够很容易地使用编码或aspnet_regiisexe(一个命令行程序)预以加密一旦被加密nfig设置即可避开虎视眈眈的眼睛而且当以编程方式从你的ASPNET页面中检索加密的配置设置时ASPNET会自动地解密它读取的加密部分简言之一旦配置信息被加密你就不需要在你的应用程序中编写任何其它代码或采取任何进一步的行为来使用该加密数据
在本文中我们将讨论如何以编程方式加密和解密该配置设置部分并且分析一下命令行程序aspnet_regiisexe的使用然后我们将评估ASPNET 提供的加密选项另外还会简短地讨论一下如何加密ASPNET版本x中的配置信息
二 前提
在我们开始探讨如何加密ASPNET 配置信息之前请记住下列几点
所有形式的加密都会包含某种秘密而当加密和解密数据时都要使用这一秘密对称加密算法在加密和解密一个消息时使用同一把密钥而非对称加密算法对于加密和解密却使用不同的密钥无论使用哪种技术最重要的还是看解密密钥的安全保存程度
ASPNET 提供的配置加密技术的设计目的在于力图阻止能够以某种方式检索你的配置文件的黑客的入侵其实现思想是如果在黑客的计算机上有你的nfig文件那么他不能破解该加密的部分然而当web服务器上的一个ASPNET页面从一个加密的配置文件请求信息时该数据必须被解密才能使用(并且这时不需要你编写任何代码)因此如果一个黑客能够把一个能够查询配置文件并显示它的结果的ASPNET web页面上传到你的系统那么他就能够以普通文本方式观看被加密的设置(详细情况请参考本文提供的示例ASPNET页面它展示了加密和解密nfig文件中各部分的方法如你所见一个ASPNET页面能够存取(并显示)该加密数据的普通文本形式)
加密和解密配置信息需要付出一定的性能代价因此通常是仅加密包含敏感信息的配置部分比如说可能不需要加密<compilation>或<authorization>配置部分
三 加密何种信息
在我们分析如何加密ASPNET 配置信息前让我们首先来看一下能够加密什么配置信息使用NET框架提供的库开发人员能够加密在nfig或nfig文件中的绝大多数的配置部分这些配置部分是一些作为<configuration>或<systemweb>元素子结点的XML元素例如下面的示例nfig文件中含有三个配置设置显式地定义为
<connectionStrings><compilation>和<authentication>
<?xml version=?>
<configuration xmlns=>
<connectionStrings>
<add name=MembershipConnectionString connectionString=connectionString/>
</connectionStrings>
<systemweb>
<compilation debug=true/>
<authentication mode=Forms />
</systemweb>
这些节中的每一个都可以有选择地被加密或者通过编程方式或通过aspnet_regiisexe(一个命令行工具)实现当被加密时加密后的文本直接存储在配置文件中例如如果我们要加密上面的<connectionStrings>节那么结果nfig文件可能看起来如下所示(注意篇幅所限我们省略了一大块<CipherValue>)
<?xml version=?>
<configuration xmlns=>
<connectionStrings configProtectionProvider=DataProtectionConfigurationProvider>
<EncryptedData>
<CipherData>
<CipherValue>AQAAANCMndBFdERjHoAwE/Cl+sBAAAAedGicAlQ==</CipherValue>
</CipherData>
</EncryptedData>
</connectionStrings>
<systemweb>
<compilation debug=true/>
<authentication mode=Forms />
</systemweb>
另外存在一些你不能使用这个技术加密的配置部分
· <processModel>
· <runtime>
· <mscorlib>
· <startup>
· <systemruntimeremoting>
· <configProtectedData>
· <satelliteassemblies>
· <cryptographySettings>
· <cryptoNameMapping>
· <cryptoClasses>
为了加密这些配置部分你必须加密这些值并把它存储在注册表中存在一个aspnet_setregexe命令行工具可以帮助你实现这一过程我们将在本文后面讨论这个工具
【提示】WebConfig和MachineConfig之区别
nfig文件指定针对一个特定的web应用程序的配置设置并且位于应用程序的根目录下而nfig文件指定所有的位于该web服务器上的站点的配置设置并且位于$WINDOWSDIR$\MicrosoftNet\Framework\Version\CONFIG目录下
四加密选项
开发人员可以使用ASPNET 提供程序模型来保护配置节信息这允许任何实现都可以被无缝地插入到该API中NET框架中提供了两个内置的提供程序用于保护配置节信息
· Windows数据保护API(DPAPI)提供程序(DataProtectionConfigurationProvider)这个提供程序使用Windows内置的密码学技术来加解密配置节默认情况下这个提供程序使用本机的密钥你还能够使用用户密钥但是这要求进行一点定制
· RSA保护的配置提供程序(RSAProtectedConfigurationProvider)使用RSA公钥加密来加解密配置节使用这个提供程序你需要创建存储用于加解密配置信息的公钥和私钥的密钥容器你能够在一个多服务器场所下使用RSA这只要创建可输出的密钥容器即可
当然如果需要的话你还能够创建自己的保护设置提供程序
在本文中我们仅讨论使用DPAPI提供程序使用机器级密钥到目前为止这是最简单的方法因为它不请求创建任何密钥或密钥容器当然其消极的一面在于一个加密的配置文件仅能够用于首先实现加密的web服务器上而且使用机器密钥将允许加密的文本能够被web服务器上的任何网站所解密
五以编程方式加密配置部分
SystemConfigurationSectionInformation类对一个配置节的描述进行了抽象为了加密一个配置节只需要简单地使用SectionInformation类的ProtectSection(提供程序)方法传递你想使用的提供程序的名字来执行加密为了存取你的应用程序的nfig文件中的一个特定的配置节你可以使用WebConfigurationManager类(在SystemWebConfiguration命名空间中)来引用你的nfig文件然后使用它的GetSection(sectionName)方法返回一个ConfigurationSection实例最后你可以经由ConfigurationSection实例的SectionInformation属性得到一个SectionInformation对象
下面我们通过一个简单的代码示例来说明问题
privatevoid ProtectSection(string sectionName string provider)
{
Configuration config = WebConfigurationManager
OpenWebConfiguration(RequestApplicationPath);
ConfigurationSection section = configGetSection(sectionName);
if (section != null &&!sectionSectionInformationIsProtected)
{
sectionSectionInformationProtectSection(provider);
configSave();
}
}
private void UnProtectSection(string sectionName) {
Configuration config =WebConfigurationManagerOpenWebConfiguration(RequestApplicationPath);
ConfigurationSection section = configGetSectio n(sectionName);
if (section != null && sectionSectionInformationIsProtected)
{
sectionSectionInformationUnprotectSection();
configSave();
}
你可以从一个ASPNET页面中调用这个ProtectSection(sectionNameprovider)方法其相应的参数是一个节名(如connectionStrings)和一个提供程序(如DataProtectionConfigurationProvider)并且它打开nfig文件引用该节调用SectionInformation对象的ProtectSection(provider)方法最后保存配置变化
另一方面UnProtectSection(provider)方法实现解密一个特定的配置节在此仅需要传入要解密的节我们不需要麻烦提供程序因为该信息已经存储在伴随encrypted节的标记中(也即是在上面的示例中的<connectionStrings>节在被加密以后它包含了提供程序<connectionStringsconfigProtectionProvider=DataProtectionConfigurationProvider>)
记住一旦该数据被加密当从一个ASPNET页面读取它时(也即是从一个SqlDataSource控件或以编程方式经由ConfigurationManagerConnectionStrings[connStringName]ConnectionString读取该连接字符串信息)ASPNET会自动地解密该连接字符串并且返回普通文本值换句话说在实现加密后你一点不需要改变你的代码相当酷对不对?
从本文下载的示例ASPNET 网站中你会发现有一个示例页面它展示了该站点的nfig文件其中有一个多行TextBox还提供了相应的Web控件按钮用于加密配置文件的各个部分这个示例中也使用了上面已经讨论过的ProtectSection()和UnProtectSection()方法
六 使用命令行工具aspnet_regiisexe你还能够使用aspnet_regiisexe命令行工具来加密和解密nfig文件配置部分你可以在%WINDOWSDIR%\MicrosoftNet\Framework\version目录下找到这个工具为了加密nfig文件中的一个节你可以在这个命令行工具中使用DPAPI机器密钥如下所示
加密一个特定网站的nfig文件的通用形式
aspnet_regiisexe pef section physical_directory prov provider
或
aspnet_regiisexe pe section app virtual_directory prov provider
加密一个特定网站的nfig文件的具体实例
aspnet_regiisexe pef connectionStrings C:\Inetpub\wwwroot\MySite prov DataProtectionConfigurationProvider
或
aspnet_regiisexe pe connectionStrings app /MySite prov DataProtectionConfigurationProvider
解密一个特定网站的nfig文件的通用形式
aspnet_regiisexe pdf section physical_directory
或
aspnet_regiisexe pd section app virtual_directory
解密一个特定网站的nfig文件的具体实例
aspnet_regiisexe pdf connectionStrings C:\Inetpub\wwwroot\MySite
或
你还能够指定由aspnet_regiisexe来执行nfig文件的加密/解密
【提示】 加密ASPNET版本x中的配置设置
为了保护ASPNET版本x中的配置设置开发者需要加密并把敏感的设置存储在web服务器的注册表中并以一种强键方式存储配置文件中不是存储加密的内容(如ASPNET 那样)而只是包含一个到存储该加密值的注册表键的引用例如
<identity impersonate=true
userName=registry:HKLM\SOFTWARE\MY_SECURE_APP\identity\ASPNET_SETREGuserName
password=registry:HKLM\SOFTWARE\MY_SECURE_APP\identity\ASPNET_SETREGpassword />
微软为开发人员提供了aspnet_setregexe命令行工具用于加密敏感的配置信息并且把它移动到一个强注册表入口处遗憾的是这个工具仅针对特定的配置设置工作相比之下ASPNET 允许加密任何配置节
有关于在一个ASPNET x应用程序中使用aspnet_setregexe的更多信息请参考MSDN中的KB#遗憾的是这个命令行程序仅能加密配置设置中的预定义的节并且不允许你加密你自己添加的数据库连接字符串和其它敏感信息
七 结论
在本文中我们学习了如何使用ASPNET 提供的不同的加密选项来保护配置节信息还讨论了如何使用编程技术和aspnet_regiisexe来分别加密nfig中的配置节保护你的敏感的配置设置有助于确保你的站点更难于被黑客攻击通过使其更难于发现敏感的配置设置如今ASPNET 已经提供了相对容易的加密和解密技术开发者毫无理由不使用这种方式来保护你的敏感的配置设置