ASP.NET2.0裏的配置API接口函數允許我們讀/寫配置文件----包括對web.config和machine.config的讀寫。您可以讀寫您自己應用程序裏的配置文件,也可以讀寫同一機器上其它應用程序的配置文件,您甚至可以讀寫不同服務器上的應用程序配置文件。本文我們將以ASP.NET開發人員的角度看一下ASP.NET2.0的新亮點,這其中包括如何加密和解密配置文件。
AppSettings 和 Connection 字符串
在ASP.NET開發中,兩個常規任務是從配置文件裏讀取應用程序的設置和數據庫鏈接字符串。在ASP.NET2.0中,這些設置分別駐留在<appSettings>和<connectionStrings>配置節。一個web.config示例看起來應該類似如下:
<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”信息,我們可以使用類似如下的代碼:
message = WebConfigurationManager.AppSettings["message"];
同樣,如果我們想獲取第二個數據庫連接字符串--連接名爲pubs的--我們可以使用如下的代碼
WebConfigurationManager.ConnectionStrings["pubs"].ConnectionString;
通過使用GetSection靜態方法,使得讀取配置文件裏的任何設置變的簡單。GetSection採用XPath表達式來響應你想讀取的節,你可以使用強類型轉換將對對象的引用轉換爲對內置節的引用。例如使用AuthorizationSection 類來操作對<authorization>節的配置,使用PageSection類來操作對<pages>節的操作。
如果我們想更改web.config裏對<identity>節模擬的設置,我們可以使用如下代碼
{
// 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>節的設置:
{
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的事件裏使用如下代碼
{
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文件
<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的文件看起來類似如下:
<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方法主要是演示如何返回未加密的節
{
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,我們將看到其配置如下:
<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>
這裏我們使用的是外部配置文件, 打開外部配置文件可以看到內容類似如下:
<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配置函數讀寫配置文件。在配置文件修改時,討論了應用程序的重啓問題。