ASP.NET2.0里的配置接口API
ASP.NET2.0里的配置API接口函数允许我们读/写配置文件----包括对web.config和machine.config的读写。您可以读写您自己应用程序里的配置文件,也可以读写同一机器上其它应用程序的配置文件,您甚至可以读写不同服务器上的应用程序配置文件。本文我们将以ASP.NET开发人员的角度看一下ASP.NET2.0的新亮点,这其中包括如何加密和解密配置文件。
AppSettings 和 Connection 字符串
在ASP.NET开发中,两个常规任务是从配置文件里读取应用程序的设置和数据库链接字符串。在ASP.NET2.0中,这些设置分别驻留在<appSettings>和<connectionStrings>配置节。一个web.config示例看起来应该类似如下:
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings>
<add key="message" value="Hello World!" />
</appSettings>
<connectionStrings>
<add name="AdventureWorks" connectionString="..."/>
<add name="pubs" connectionString="..."/>
</connectionStrings>
<system.web>
<compilation debug="true" />
<authentication mode="Windows"/>
<identity impersonate="true"/>
</system.web>
</configuration>
ASP.NET提供的API接口函数是以WebConfigurationManager类开始的,该类在System.Web.Configuration命名空间。WebConfigurationManager类包含了静态方法以获取应用程序的设置和数据库连接字符串。例如为了读取上面示例中appSetting的“message”信息,我们可以使用类似如下的代码:
string message;
message = WebConfigurationManager.AppSettings["message"];
同样,如果我们想获取第二个数据库连接字符串--连接名为pubs的--我们可以使用如下的代码
string connectionString =
WebConfigurationManager.ConnectionStrings["pubs"].ConnectionString;
通过使用GetSection静态方法,使得读取配置文件里的任何设置变的简单。GetSection采用XPath表达式来响应你想读取的节,你可以使用强类型转换将对对象的引用转换为对内置节的引用。例如使用AuthorizationSection 类来操作对<authorization>节的配置,使用PageSection类来操作对<pages>节的操作。
如果我们想更改web.config里对<identity>节模拟的设置,我们可以使用如下代码
protected void readImpersonationButton_Click(object sender, EventArgs e)
{
// note: currently broken in BETA2, works in post BETA2 builds.
// in BETA2 GetSection returns a wrapper
// that will not cast to IdentitySection
IdentitySection section;
section = WebConfigurationManager.GetSection("system.web/identity")
as IdentitySection;
if (section != null)
{
WriteMessage("Impersonate = " + section.Impersonate);
}
}
private void WriteMessage(string message)
{
// this method assumes a PlaceHolder control
// on the web form with the ID of messagePlaceHolder
HtmlGenericControl generic = new HtmlGenericControl();
generic.InnerHtml = message;
messagePlaceHolder.Controls.Add(generic);
}
又如对<pages>节的设置:
protected void readImpersonationButton_Click(object sender, EventArgs e)
{
System.Configuration.Configuration config = WebConfigurationManager.OpenWebConfiguration(path);
PagesSection pages = (PagesSection)config.GetSection("system.web/pages");
this.lblSession.Text = pages.EnableSessionState.ToString();
this.lblViewState.Text = pages.EnableViewState.ToString();
this.lblMaxPage.Text = pages.MaxPageStateFieldLength.ToString();
this.lblAutoEvent.Text = pages.AutoEventWireup.ToString();
//获取整节appSettings相关的XML格式代码
ConfigurationSection appSettings = config.GetSection("appSettings");
this.Label1.Text=Server.HtmlEncode(appSettings.SectionInformation.GetRawXml());
}
修改配置文件
WebConfigurationManager 类提供静态方法OpenWebConfiguration同样允许我们打开web的配置文件并进行更新。我们可以通过根据传递应用程序的相对路径来指明需要打开哪个应用程序的配置文件。我们还可以通过传递IIS 站点名称和虚拟路径的名称来读取其它应用程序的配置问题。使用后面这种方式,就可以读取其它应用程序的配置文件。
如果我们想获取当前应用程序web.config里<compliation>配置节的debug属性,更改debug为true或者为false,我们可以使用在button的事件里使用如下代码
protected void toggleDebugButton_Click(object sender, EventArgs e)
{
string path = Request.CurrentExecutionFilePath;
path=path.Substring(0,path.LastIndexOf("/"));
Configuration config;
config = WebConfigurationManager.OpenWebConfiguration(path);
CompilationSection compilation;
compilation = config.GetSection("system.web/compilation")
as CompilationSection;
if (compilation != null)
{
compilation.Debug = !compilation.Debug;
config.Save();
WriteMessage(
"Debug setting is now: " + compilation.Debug
);
}
}
使用强类型的CompilationSection对象允许我们读写<compliation>节里的属性。我们可以改变节的配置并使用 System.Configuration.Configuration 里的Save保存所有的修改。
在更改配置文件时,还有一个小的细节,首先,你应该具有修改配置文件的权限,典型的启动.NET runtime运行时的NETWORD SERVICE和ASPNET帐户并没有修改应用程序里配置文件的权限。
一个安全的解决方法是使用基于windows的身份验证并启用模拟技术。这些设置允许客户端执行请求的任务。如果客户端具有修改配置文件的权限,上面的操作才能够成功。
另外一个注意事项是ASP.NET runtime将随时监视web.config,一旦web.config有了改动,ASP.NET将重新启动应用程序。具体的说 ASP.NET运行时将根据你更改web.config所在的应用程序域,重新建立应用程序对象实例。重建实例对性能有显著影响,所以不应该经常修改web.config。
如果你想要在修改web.config时,既能够获取更多的控制权限同时又不使应用程序重新启动,你可以使用外部配置文件,下一节将介绍这个问题。
使用外部配置文件
你可以将配置文件里的任意配置节取出并单独存放,例如我们看一下新的配置web.config文件
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings configSource="appSettings.config"/>
<connectionStrings configSource="connections.config"/>
<system.web>
<compilation debug="true" />
<authentication mode="Windows"/>
<identity impersonate="true"/>
</system.web>
</configuration>
在这个例子中,我们将<appSettings> 和 <connectionStrings>的配置移动到了web.config的外部,这些外部文件同样是基于XML格式的配置节片段,例如appSettings.config的文件看起来类似如下:
<appSettings>
<add key="message" value="Hello World!"/>
</appSettings>
使用外部配置文件在某些情况下较为有用,例如在开发,或者在测试甚至在成品软件开发中,由于阶段的不同我们需要一种简易的方式切换设置,此时就可以使用外部配置文件。
如果你需要更多的控制权限也可以使用外部配置,例如你对你的web.config进行了锁定,只有Administrators用户可以更改该配置问题,但是你可以让<appSettings>节使用外部配置文件并允许其它角色的用户修改其内容。
使用外部文件还有其它的优越性--它可以控制我们的应用程序是否重新启动。 如果在web.config里进行了改动。ASP.NET应用程序总会重新启动--不存在选择的余地,但是使用外部文件,你可以告诉runtime运行时,是否在外部文件改动时重启应用程序。
如果你查看machine.config里的配置,在<configSections>节,你可以看到每一个节定义的处理句柄(Handler)。每一个节包含一个属性:restartOnExternalChanges。
请注意对appSettings的配置,其restartOnExternalChanges设置为"false",这意味这如果使用外部文件存放设置信息,当外部文件改变时,应用程序并不重新启动,但是你使用WebConfigurationManager.AppSettings读取的将是新值。
在使用restartOnExternalChanges 请注意,有些外部文件改变时,必须重启应用程序才能够生效。在这种情况下,虽然你可以设置restartOnExternalChanges 为false,但是请确保不要在应用程序里缓存节的参数,并重新使用WebConfigurationManager读取配置值。
使用加密
在ASP.NET2.0里提供了对配置节直接加密的功能。在配置文件里有几处配置可能包含敏感信息,例如<connectionStrings> 节,它可能包含连接数据库的用户名和密码。<identity>节可能包含runtime使用模拟帐户的用户和密码。 你甚至可能在配置文件的appSettings里或者在自定义节里包含共享web service使用的密码。不管哪种情况,您都不希望密码以明文的方式存放在配置文件里。
注意:在配置文件里也包含你无法加密的节,主要是<precessModul>节。此时你可以需要利用ASPNET_SETREG.EXE工具单独设置该节密码。
下面的代码演示了加密和解密节是多么的简单,注意:在从节里读取配置信息时,你不需要解密。ASP.NET运行时会自动读取加密的文本,并在应用程序需要的地方自动解密加密的信息。在这里调用Unprotect方法主要是演示如何返回未加密的节
protected void toggleEncryptionButton_Click(object sender, EventArgs e)
{
Configuration config;
config = WebConfigurationManager.OpenWebConfiguration("~");
ConnectionStringsSection section;
section = config.GetSection("connectionStrings")
as ConnectionStringsSection;
if (section.SectionInformation.IsProtected)
{
section.SectionInformation.UnprotectSection();
}
else
{
section.SectionInformation.ProtectSection(
"DataProtectionConfigurationProvider"
);
}
config.Save();
WriteMessage("connections protected = " +
section.SectionInformation.IsProtected);
}
在执行上述代码后,如果我们检测web.config,我们将看到其配置如下:
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<protectedData>
<protectedDataSections>
<add name="connectionStrings"
provider="DataProtectionConfigurationProvider"
inheritedByChildren="false" />
</protectedDataSections>
</protectedData>
<appSettings configSource="appSettings.config"/>
<connectionStrings configSource="connections.config"/>
<system.web>
<compilation debug="true" />
<authentication mode="Windows"/>
<identity impersonate="true"/>
</system.web>
</configuration>
这里我们使用的是外部配置文件, 打开外部配置文件可以看到内容类似如下:
<connectionStrings>
<EncryptedData>
<CipherData>
<CipherValue>AQAAANCMnd8BF....</CipherValue>
</CipherData>
</EncryptedData>
</connectionStrings>
运行时,ASP.NET解密区域信息,我们可以仍然使用WebConfigurationManager.ConnectionStrings 返回应用程序可以直接使用的数据库连接字符串。
为了理解配置文件,我们首先需要明白名运行时是怎么处理加密和解密工作的。解密和解密分别使用了Provider模型,ASP.NET2.0使用这两个Provider模型分别是:DataProtectionConfigurationProvider 和RSAProtectedConfigurationProvider (如果需要,你也可以自定义自己的加密/解密Provider)
我们可以通过传递给ProtectSetion的参数来指示使用Provider的具体模型。在前面代码片段中,我们使用的是DataProtectionConfigurationProvider
DataProtectionConfigurationProvider 使用Windows Data Protection API (DPAPI)接口,这提供了加密和解密的工作,因为Windows Data Protection API (DPAPI)依赖于具体的机器密钥。只有在同一机器上,针对加密的解密才有效。
如果你需要将配置从一台机器转移到另外一台机器,你需要使用RSAProtectedConfigurationProvider模型。RSAProtectedConfigurationProvider,正如其名称所示意,使用RSA作为加密密钥。 你可以使用具有RSAProtectedConfigurationProvider功能的aspnet_regiis.exe命令进行操作。aspnet_regiis.exe包含一些列参数包括建立密钥对(-pc),导出密码(-pc)等
总结
本文介绍了如何使用API配置函数读写配置文件。在配置文件修改时,讨论了应用程序的重启问题。
源文地址
http://odetocode.com/Articles/418.aspx