Configuring Applications


ASP.NET uses a hierarchical system of configuration. At the top of the hierarchy is the Machine.config file. This file contains all the default configuration settings for ASP.NET applications and all other types of applications built with the .NET Framework.

The Machine.config file is located at the following path:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\Machine.config

This same folder also contains a Web.config file. The Web.config file contains settings specific to ASP.NET applications. The Web.config file overrides particular settings in the Machine.config file.

The \CONFIG folder includes the following six files:
Machine.config—Contains the actual configuration settings.
Machine.config.default—Contains the default values for all configuration settings.
Machine.config.comments—Contains comments on each configuration setting.
Web.config—Contains the actual configuration settings.
Web.config.default—Contains the default values for all configuration settings.
Web.config.comments—Contains comments on each configuration setting.

Only the Machine.config and Web.config files are actually used. The other files are there for the purpose of documentation. You can place a Web.config file in the root folder of a website, such as the wwwroot
folder. A Web.config file located in the root folder of a website contains settings that apply to all applications contained in the website. You also can place a Web.config file in the root of a particular application. In that case, the Web.config file has application scope. Finally, you can place a Web.config file in an application subfolder. In that case, the Web.config file applies to all pages in that folder and below.


When an ASP.NET application starts, this hierarchy of configuration files is merged and cached in memory. A file dependency is created between the cached configuration settings and the file system. If you make a change to any of the configuration files in the hierarchy, the new configuration settings are loaded into memory automatically. When an ASP.NET page reads a configuration setting, the setting is read from memory. This means that the ASP.NET Framework can read configuration settings, such as connection strings, very efficiently.

Modifying most configuration settings results in an application restart. Any data stored using the cache or in-process Session state is lost and must be reloaded. You can get around this issue by using external configuration files. See the section “Placing Configuration Settings in an External File” later in this chapter. The configuration files are XML files. You can modify configuration settings by opening the Machine.config file or a Web.config file and modifying a setting in Notepad. Alternatively, you can change many of the configuration settings (but not all) by using either the Web Site Administration Tool or the ASP.NET Microsoft Management Console Snap-In. Using the Web Site Administration Tool If you are using Visual Web Developer (or Visual Studio .NET), then you can modify certain configuration settings with the Web Site Administration Tool. This tool provides you with a form interface for making configuration changes. You open the Web Site Administration Tool by selecting the menu option Website, ASP.NET Configuration. Selecting this option opens a browser window that contains the tool.
The Web Site Administration Tool has the following four tabs:
Home—This tab contains links to the other tabs.
Security—This tab enables you to configure authentication, authorization, and the Role Manager.
Application—This tab enables you to create and manage application settings, configure SMTP settings, and enable application tracing, debugging, and error pages.

You also can use this tab to take your application offline.
Provider—This tab enables you to select a provider for Membership and the Role Manager.

Under the Application tab, you can click the link to take your application offline. When you click this link, the following httpRuntime element is added to your web configuration file:
 <httpRuntime enable=”false” />

This setting causes the Application Domain associated with the ASP.NET application to refuse any requests. When an application is offline, all requests result in a 404—Not Found error message. You might want to take your application offline, for example, to prevent people from requesting pages while you perform updates to your application.

You also can take an ASP.NET application offline by adding a file with the name app_offline.htm to the root of your application. The Web Site Administration Tool is implemented as an ASP.NET application. Behind the scenes, it uses the Configuration API that is discussed later in this chapter. You can view the entire source code for the Web Site Administration Tool by navigating to the following folder:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ASP.NETWebAdminFiles

Using the ASP.NET Microsoft Management Console Snap-In
You also can make configuration changes with the ASP.NET Microsoft Management Console (MMC) Snap-In tool (see Figure 28.2). You can open the ASP.NET MMC Snap-In by following these steps:
1. Open Internet Information Services from Start, Control Panel, Administrative Tools.
2. Open the property sheet for either a website or a virtual directory.
3. Select the ASP.NET tab.
4. Click the Edit Configuration (or Edit Global Configuration) button.

The ASP.NET MMC Snap-In includes the following tabs:
General—Enables you to configure connection strings and application settings.
Custom Errors—Enables you to configure custom error pages.

Overview of Website Configuration

Authorization—Enables you to configure authorization rules.
Authentication—Enables you to configure Forms, Windows, or Passport authentication.
Application—Enables you to configure application settings such as application-wide Master Pages and Themes.
State Management—Enables you to configure Session state.
Locations—Enables you to apply configuration settings to a particular folder or page.

Behind the scenes, the ASP.NET MMC Snap-In uses the Configuration API to make changes to web configuration files.

ASP.NET Configuration Sections
All the configuration sections in the Machine.config or Web.config file related to ASP.NET are contained in the <system.web> section group. Here is a complete list of the 36 ASP.NET configuration sections and a brief explanation of the purpose of each section:

anonymousIdentification—Enables you to configure anonymous user identification, which is used, for example, by the Profile object.
authentication—Enables you to configure authentication.
authorization—Enables you to configure authorization.
browserCaps—Enables you to configure the lookup of browser capabilities.
caching—Enables you to configure caching.
clientTarget—Enables you to configure aliases for different clients (browsers).
compilation—Enables you to configure how ASP.NET applications are compiled.For example, you can specify whether an application is compiled in debug mode.
customErrors—Enables you to configure custom error pages.
deployment—Enables you to specify whether an ASP.NET application is deployed in retail mode.
deviceFilters—Enables you to configure device filters.
globalization—Enables you to configure the Culture, UICulture, and other attributes related to building multi-lingual web applications.
healthMonitoring—Enables you to configure Health Monitoring.
hostingEnvironment—Enables you to configure ASP.NET application properties such as the application idle timeout.
httpCookies—Enables you to configure how cookies are sent to the browser.
httpHandlers—Enables you to configure HTTP Handlers.
httpRuntime—Enables you to configure properties of the HTTP Runtime, such as the number of threads maintained in the thread pool.
httpModules—Enables you to configure HTTP Modules.
identity—Enables you to configure the identity of the ASP.NET application account.
machineKey—Enables you to configure encryption keys used by Membership and Session state.
membership—Enables you to configure ASP.NET Membership.
mobileControls—Enables you to configure adapters used with ASP.NET mobile controls.

Overview of Website Configuration
pages—Enables you to configure page properties such as the website Master Page and Theme
processModel—Enables you to configure the ASP.NET process.
profile—Enables you to configure the Profile object.
roleManager—Enables you to configure the Role Manager.
securityPolicy—Enables you to map security policy files to trust levels.
sessionPageState—Enables you to configure how mobile devices store Session state.
sessionState—Enables you to configure Session state.
siteMap—Enables you to configure Site Maps.
trace—Enables you to configure page and application tracing.
trust—Enables you to configure Code Access Security (CAS) for an ASP.NET application.
urlMappings—Enables you to remap page requests to new pages.
webControls—Enables you to specify the location of client-script files used by web controls.
webParts—Enables you to configure Web Parts.
webServices—Enables you to configure web services.
xhtmlConformance—Enables you to configure the level of XHTML conformance of the XHTML rendered by web controls.

Applying Configuration Settings to a Particular Path
By default, the settings in a Machine.config or Web.config file are applied to all pages in the same folder and below. However, if you have the need, you can also apply configuration settings to a particular path. For example, you can apply configuration settings to a particular subfolder or even a particular page. You apply configuration settings to a particular path by using the <location> element. For example, the web configuration file in Listing enables password-protection for a single file named Secret.aspx.

LISTING Web.config
<configuration >
<system.web>
<authentication mode=”Forms” />
</system.web>
<location path=”Secret.aspx”>
<system.web>
<authorization>
<deny users=”?” />
</authorization>
</system.web>
</location>
</configuration>

If you attempt to request the Secret.aspx page, you are redirected to the Login.aspx page. However, none of the other files in the same application are password protected by the configuration file. The <location> element must be added as an immediate child of the <configuration> element. You can’t, for example, add the <location> element within a <system.web> element. You must surround the <system.web> element with the <location> element. You can create the web configuration file in Listing by selecting the menu option Website, Add New Item, and selecting the Web Configuration File template.

Alternatively, you can add the appSettings section by using either the Web Site Administration Tool or the ASP.NET MMC Snap-In. Both tools enable you to enter values for the appSettings section through a user-friendly interface.

Locking Configuration Settings
You can lock configuration settings so that they cannot be overridden at a lower level in the configuration hierarchy. For example, you might want to require that no application running on your production server execute in debug mode. In that case, you can lock the debug configuration setting in a website Web.config file, the root Web.config file, or the Machine.config file. You can lock a configuration setting in multiple ways. The Web.config file in Listing illustrates how you can lock a setting by using the allowOverride=”false” attribute of the <location> element.

LISTING Web.config
<configuration >
<location allowOverride=”false”>
<system.web>
<compilation debug=”false” />
</system.web>
</location>
</configuration>

As an alternative to locking the compilation section to prevent a production website being deployed in debug mode, you can take advantage of the deployment element. Adding the following element to the system.web section of the machine.config disables debug mode, enables remote custom errors, and disables trace:
<deployment retail=”true” />

One problem with the configuration file in Listing is that it locks the entire compilation element. If you attempt to change any attribute of the compilation element at a lower level in the configuration hierarchy, then an exception is raised. You can add any of the following attributes to a particular configuration element to lock either the entire element or one or more of its attributes:

lockAllAttributesExcept—Enables you to lock all attributes except those listed as the value of this attribute. You can specify multiple attributes to exclude in a comma-delimited list.
lockAllElementsExcept—Enables you to lock all child elements of the current element except those listed as the value of this attribute. You can specify multiple elements to exclude in a comma-delimited list.
lockAttributes—Enables you to lock multiple attributes. You can specify the attributes to lock in a comma-delimited list.
lockElements—Enables you to lock multiple child elements. You can specify the child elements to lock in a comma-delimited list.
lockItem—Enables you to lock the current element.

For example, the web configuration file in Listing locks the debug attribute, and only the debug attribute, of the <compilation> element.

LISTING Web.config
<configuration >
<system.web>
<compilation debug=”false” lockAttributes=”debug” />
</system.web>
</configuration>

Adding Custom Application Settings
You can add custom configuration settings to the web configuration file easily by taking advantage of the appSettings section. The appSettings section contains a list of key and value pairs. For example, the web configuration file in Listing contains a welcome message and a copyright notice.

LISTING Web.config
<configuration>
<appSettings>
<add key=”welcome” value=”Welcome to our Web site!” />
<add key=”copyright” value=”Copyright (c) 2007 by the company” />
</appSettings>
</configuration>

You can retrieve values from the appSettings section either programmatically or declaratively. The page in Listing illustrates both approaches.

LISTING ShowAppSettings.aspx
<%@ Page Language=”C#” %>
<%@ Import Namespace=”System.Web.Configuration” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<script runat=”server”>
void Page_Load()
{
lblWelcome.Text = WebConfigurationManager.AppSettings[“welcome”];
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
FIGURE 28.4 Displaying values from the appSettings configuration section.
1454 CHAPTER 28 Configuring Applications
LISTING 28.5 Continued
<head id=”Head1” runat=”server”>
<title>Show AppSettings</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:Label id=”lblWelcome” Runat=”server” />
<hr />
<asp:Literal id=”ltlCopyright” Text=”<%$ AppSettings:copyright %>” Runat=”server” />
</div>
</form>
</body>
</html>

Placing Configuration Settings in an External File
You can place particular configuration sections in an external file. You might want to do this for a couple of reasons. First, you can make a configuration file more manageable by dividing it into multiple files. Also, when you place configuration information in a separate file, you can prevent application restarts when you change a configuration setting. Every configuration element includes a configSource attribute. You can assign a path to a file as the value of the configSource attribute. For example, the web configuration file in Listing 28.6 uses the configSource attribute in its <appSettings> element.

LISTING Web.config
<configuration>
<appSettings configSource=”appSettings.config” />
</configuration>
<appSettings>
<add key=”message” value=”Hello World!” />
</appSettings>

Using the Configuration API
The Configuration API enables you to retrieve and modify configuration settings. You can use the Configuration API to modify web configuration files on the local machine or a remote machine. If you are responsible for maintaining a large number of websites, the Configuration API can make your life much easier. You can build administrative tools that enable you to make configuration changes quickly to multiple applications. You can use the Configuration API in an ASP.NET page, or you can build command-line tools or Windows Forms applications that use the Configuration API.

The Configuration API is exposed by the WebConfigurationManager class (located in the System.Web.Configuration namespace). This class supports the following properties:

AppSettings—Exposes all the settings from the appSettings section.
ConnectionStrings—Exposes all the settings from the connectionStrings section.

The WebConfigurationManager also supports the following methods:
GetSection—Retrieves a configuration section relative to the current page or a supplied virtual path.
GetWebApplicationSection—Retrieves a configuration section from the current web application root web configuration file.
OpenMachineConfiguration—Retrieves a Machine.config file on either the local machine or a remote server.
OpenMappedMachineConfiguration—Retrieves a Machine.config file by using a particular file mapping.
OpenMappedWebConfiguration—Retrieves a web configuration file by using a particular file mapping.
OpenWebConfiguration—Retrieves a Web.config file on either the local machine or a remote server.

Almost every configuration section in the web configuration file has a corresponding class in the .NET Framework that represents the configuration section. These classes provide you with a strongly typed representation of each configuration section. For example, corresponding to the <authentication> section in the web configuration file, there is a System.Web.Configuration.AuthenticationSection class. Corresponding to the <pages> section in the web configuration file, there is a System.Web. Configuration.PagesSection class. Each of these classes expose properties that correspond to all the attributes you can set in the web configuration file.

Reading Configuration Sections from the Current Application
When an ASP.NET application starts, the application merges all the configuration settings in the configuration hierarchy to create one representation of the configuration settings. A particular configuration setting might have different values at different levels in the hierarchy. You can use the methods of the WebConfigurationManager class to get the value of a configuration setting at any level in the hierarchy.

The WebConfigurationManager.GetWebApplicationSection() method always retrieves a configuration setting from the application root Web.config file. For example, the page in Listing 28.8 displays whether debugging is enabled.

LISTING ShowConfigApp.aspx
<%@ Page Language=”C#” %>
<%@ Import Namespace=”System.Web.Configuration” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<script runat=”server”>
void Page_Load()
{
CompilationSection section = (CompilationSection)WebConfigurationManager.
GetWebApplicationSection(“system.web/compilation”);
lblDebug.Text = section.Debug.ToString();
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<title>Show Config App</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
Debug Mode:
<asp:Label id=”lblDebug” Runat=”server” />
</div>
</form>
</body>
</html>

The GetWebApplication() method returns an object. You must cast the value returned by this method to a particular configuration section type. In Listing, the value returned by this method is cast to an instance of the CompilationSection type. Realize that you will get the same result when the page in Listing is located in different subfolders. For example, debugging might not be enabled in a root configuration file, but it might be enabled in a configuration file in a particular subfolder. However, if you call the GetWebApplicationSection() method, the method always returns the configuration setting for the application root Web.config file.

If you want to get the value of a configuration setting relative to the folder in which the page executes, then you can use the GetSection() method instead of the GetWebApplicationSection() method. The page in Listing is located in a subfolder. The page displays the value of the debug setting retrieved from both the GetWebApplicationSection() method and the GetSection() method.

LISTING SubFolder\ShowConfigRelative.aspx
<%@ Page Language=”C#” %>
<%@ Import Namespace=”System.Web.Configuration” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<script runat=”server”>
void Page_Load()
{
CompilationSection section =
(CompilationSection)WebConfigurationManager.GetSection(“system.web/compilation”);
lblDebug1.Text = section.Debug.ToString();
section = (CompilationSection)WebConfigurationManager.
GetWebApplicationSection(“system.web/compilation”);
lblDebug2.Text = section.Debug.ToString();
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<title>Show Config Relative</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
GetSection Debug:
<asp:Label id=”lblDebug1” Runat=”server” />
<br /><br />
GetWebApplicationSection Debug:
<asp:Label id=”lblDebug2” Runat=”server” />
</div>
</form>
</body>
</html>

Before you can use the classes from the System.DirectoryServices namespace, you must add a reference to the System.DirectoryServices.dll assembly. In Visual Web Developer, select the menu option Website, Add Reference.

Opening a Configuration File on a Remote Server
You can use the WebConfigurationManager class to open Machine.config or Web.config files located on remote web servers. However, before you can do this, you must perform one configuration step. You must enable the remote server to accept remote configuration connections by executing the following command from a command prompt:
aspnet_regiis -config+

To disable remove configuration connections, execute the following command: aspnet_regiis -config-
The aspnet_regiis tool is located in the following path:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe

If you open the SDK Command Prompt, then you don’t need to navigate to the Microsoft.NET folder to execute the aspnet_regiis tool. After you make this modification to a remote server, you can retrieve (and modify) configuration settings on the remote server by using one of the Open methods exposed by the WebConfigurationManager class. For example, the page in Listing contains a form that enables you to enter a server, username, and password. When you submit the form, the page connects to the remote server and retrieves its Machine.config file. The page displays the current value of the remote server’s authentication mode).

LISTING ShowConfigRemote.aspx
<%@ Page Language=”C#” %>
<%@ Import Namespace=”System.Web.Configuration” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<script runat=”server”>
protected void btnSubmit_Click(object sender, EventArgs e)
{
try
{
Configuration config = WebConfigurationManager.
OpenMachineConfiguration(null, txtServer.Text, txtUserName.Text,
txtPassword.Text);
AuthenticationSection section = (AuthenticationSection)config.
GetSection(“system.web/authentication”);
lblAuthenticationMode.Text = section.Mode.ToString();
}
catch (Exception ex)
{
lblAuthenticationMode.Text = ex.Message;
}
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<title>Show Config Remote</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:Label id=”lblServer” Text=”Server:” AssociatedControlID=”txtServer” Runat=”server” />
<br />
<asp:TextBox id=”txtServer” Runat=”server” />
<br /><br />
<asp:Label id=”lblUserName” Text=”User Name:” AssociatedControlID=”txtUserName”
Runat=”server” />
<br />
<asp:TextBox id=”txtUserName” Runat=”server” />
<br /><br />
<asp:Label id=”lblPassword” Text=”Password:” AssociatedControlID=”txtPassword”
Runat=”server” />
<br />
<asp:TextBox id=”txtPassword” TextMode=”Password” Runat=”server” />
<br /><br />
<asp:Button id=”btnSubmit” Text=”Submit” OnClick=”btnSubmit_Click” Runat=”server” />
<hr />
Authentication Mode:
<asp:Label id=”lblAuthenticationMode” Runat=”server” />
</div>
</form>
</body>
</html>

Modifying Configuration Sections
You can use the WebConfigurationManager class not only when opening a configuration file to read the values of various configuration settings but to modify existing configuration settings or add new ones.
The Configuration class supports two methods for saving configuration information: the Save() and SaveAs() methods.

Creating a Configuration Element Collection
A configuration element can contain a collection of child elements. For example, if you need to create a custom configuration section to configure a provider, then you use child elements to represent the list of providers. The class in Listing represents a configuration section for a ShoppingCart. The configuration section includes three properties: MaximumItems, DefaultProvider, and Providers. The Providers property represents a collection of shopping cart providers.

LISTING App_Code\ShoppingCartSection.cs
using System;
using System.Configuration;
namespace AspNetUnleashed
{
public class ShoppingCartSection : ConfigurationSection
{
[ConfigurationProperty(“maximumItems”, DefaultValue = 100, IsRequired =
true)]
public int MaximumItems
{
get { return (int)this[“maximumItems”]; }
set { this[“maximumItems”] = value; }
}
[ConfigurationProperty(“defaultProvider”)]
public string DefaultProvider
{
get { return (string)this[“defaultProvider”]; }
set { this[“defaultProvider”] = value; }
}
[ConfigurationProperty(“providers”, IsDefaultCollection = false)]
public ProviderSettingsCollection Providers
{
get { return (ProviderSettingsCollection)this[“providers”]; }
}
public ShoppingCartSection(int maximumItems, string defaultProvider)
{
this.MaximumItems = maximumItems;
this.DefaultProvider = defaultProvider;
}
1484 CHAPTER 28 Configuring Applications
LISTING 28.21 Continued
public ShoppingCartSection()
{
}
}
}

The Providers property returns an instance of the ProviderSettingsCollection class. This class is contained in the System.Configuration namespace. The web configuration file in Listing illustrates how you can use the ShoppingCartSection.

LISTING Web.config
<configuration>
<configSections>
<sectionGroup name=”system.web”>
<section name=”shoppingCart” type=”AspNetUnleashed.ShoppingCartSection” allowLocation=”true”
allowDefinition=”Everywhere” />
</sectionGroup>
</configSections>
<system.web>
<shoppingCart maximumItems=”50” defaultProvider=”SqlShoppingCartProvider”>
<providers>
<add name=”SqlShoppingCartProvider” type=”AspNetUnleashed.SqlShoppingCartProvider” />
<add name=”XmlShoppingCartProvider” type=”AspNetUnleashed.XmlShoppingCartProvider” />
</providers>
</shoppingCart>
</system.web>
</configuration>

LISTING  App_Code\AdminUsersSection.cs
using System;
using System.Configuration;
namespace AspNetUnleashed
{
public class AdminUsersSection : ConfigurationSection
{
[ConfigurationProperty(““, IsDefaultCollection = true)]
public AdminUsersCollection Users
{
get { return (AdminUsersCollection)this[““]; }
}
public AdminUsersSection()
{
}
}
public class AdminUsersCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new AdminUser();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((AdminUser)element).Name;
}
public AdminUsersCollection()
{
this.AddElementName = “user”;
}
}
public class AdminUser : ConfigurationElement
{
[ConfigurationProperty(“name”, IsRequired = true, IsKey = true)]
public string Name
{
get { return (string)this[“name”]; }
set { this[“name”] = value; }
}
[ConfigurationProperty(“password”, IsRequired = true)]
public string Password
{
get { return (string)this[“password”]; }
set { this[“password”] = value; }
}
}
}

Notice that the ConfigurationProperty attribute that decorates the Users property sets the name of the configuration attribute to an empty string. It also marks the property as representing the section’s default collection. These options enable you to avoid having to create a subtag for the user collection. The user collection appears immediately below the main <adminUsers> section tag.

The ASP.NET page in Listing displays all the users from the adminUsers section in a BulletedList control

LISTING ShowAdminUsersSection.aspx
<%@ Page Language=”C#” %>
<%@ Import Namespace=”AspNetUnleashed” %>
<%@ Import Namespace=”System.Web.Configuration” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<script runat=”server”>
void Page_Load()
{
// Get configuration
AdminUsersSection section = (AdminUsersSection)WebConfigurationManager.
GetWebApplicationSection(“system.web/adminUsers”);
// Bind section to GridView
bltAdminUsers.DataSource = section.Users;
bltAdminUsers.DataBind();
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<title>Show AdminUsersSection</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<h1>Administrators</h1>
<asp:BulletedList
id=”bltAdminUsers”
DataTextField=”Name”
Runat=”server” />
</div>
</form>
</body>
</html>


Creating Encrypted Configuration Sections
If you need to protect sensitive information stored in a configuration file, you can encrypt the information. For example, you should always encrypt the connectionStrings section of a configuration file to prevent your database connection strings from being stolen by evil hackers. You can encrypt just about any section in the web configuration file. You can encrypt any of the sections in the system.web section group with the sole exception of the processModel section. You also can encrypt a custom configuration section.

The .NET Framework uses the Provider model for encrypting configuration sections. The Framework ships with two ProtectedConfigurationProviders: the RsaProtectedConfigurationProvider and the DpapiProtectedConfigurationProvider. The RsaProtectedConfigurationProvider protect sensitive information stored in a configuration file, you can encrypt is the default provider. It uses the RSA algorithm to protect a configuration section. The RSA algorithm uses public key cryptography. It depends on the fact that no one has discovered an efficient method to factor large prime numbers.

The second provider, the DpapiProtectedConfigurationProvider, uses the Data Protection API (DPAPI) to encrypt a configuration section. The DPAPI is built into the Windows operating system (Microsoft Windows 2000 and later). It uses either Triple-DES or AES (the United States Government–standard encryption algorithm) to encrypt data. The RsaProtectedConfigurationProvider is the default provider, and it is the one that you should almost always use. The advantage of the RsaProtectedConfigurationProvider is that this provider supports exporting and importing encryption keys. This means that you can move an application that contains an encrypted configuration file from one web server a new web server. For example, you can encrypt a configuration section on your development web server and deploy the application to a production server. If you use the DpapiProtectedConfigurationProvider to encrypt a configuration section, on the other hand, then you cannot decrypt the configuration section on another web server. If you need to move the configuration file from one server to another, then you need to first decrypt the configuration file on the source server and re-encrypt the configuration file on the destination server.

The .NET Framework uses the World Wide Web Consortium (W3C) recommendation for encrypting XML files. This recommendation is located at www.w3.org/TR/2002/REC-xmlenc-core-20021210. You can use encryption not only with configuration files, but also with other XML files.

To learn more about encrypting XML files, look up the EncryptedXml class in the Microsoft .NET Framework SDK Documentation.

Encrypting Sections with the aspnet_regiis tool
The easiest way to encrypt a section in the web configuration file is to use the aspnet_regiis command-line tool. This tool is located at the following path:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe

You don’t need to navigate to the Microsoft.NET directory to execute the aspnet_regiis tool if you open the SDK Command Prompt. If you want to encrypt a particular section of a configuration file, then you can use the -pef option when executing the aspnet_regiis tool. For example, the following command encrypts the connectionStrings section of a configuration file located in a folder named MyWebApp:
aspnet_regiis -pef connectionStrings c:\Websites\MyWebApp

If you prefer, rather than specify the location of a web application by its file system path, you can use its virtual path. The following command encrypts the connectionStrings section of a configuration file located in a virtual directory named /MyApp:
aspnet_regiis -pe connectionStrings -app /MyApp

Notice that the -app option is used to specify the application’s virtual path. You can decrypt a configuration section by using the -pdf option. The following command decrypts a configuration file located in a folder named MyWebApp:
aspnet_regiis -pdf connectionStrings c:\Websites\MyWebApp

You also can decrypt a configuration section by specifying a virtual directory. The following command uses the -pd option with the -app option:
aspnet_regiis -pd connectionStrings -app /MyApp

If you execute the following command, then the connectionStrings section is encrypted with the DataProtectionConfigurationProvider:
aspnet_regiis -pe connectionStrings -app /MyApp –prov ProtectedConfigurationProvider

Notice that this command includes a -prov option that enables you to specify the ProtectedConfigurationProvider.

Encrypting Sections Programmatically
Instead of using the aspnet_regiis tool to encrypt configuration sections, you can use the Configuration API. Specifically, you can encrypt a configuration section by calling the SectionInformation.ProtectSection() method. For example, the ASP.NET page in Listing displays all the sections contained in the system.web section group in a GridView control. You can click Protect to encrypt a section, and you can click UnProtect to decrypt a section (see Figure 28.14).
LISTING EncryptConfig.aspx
<%@ Page Language=”C#” %>
<%@ Import Namespace=”System.Web.Configuration” %>
<%@ Import Namespace=”System.Collections.Generic” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<script runat=”server”>
void Page_Load()
{
if (!Page.IsPostBack)
BindSections();
}
protected void grdSections_RowCommand(object sender, GridViewCommandEventArgs e)
{
int rowIndex = Int32.Parse((string)e.CommandArgument);
string sectionName = (string)grdSections.DataKeys[rowIndex].Value;
if (e.CommandName == “Protect”)
ProtectSection(sectionName);
if (e.CommandName == “UnProtect”)
UnProtectSection(sectionName);
BindSections();
}
private void ProtectSection(string sectionName)
{
Configuration config = WebConfigurationManager.OpenWebConfiguration
(Request.ApplicationPath);
ConfigurationSection section = config.GetSection(sectionName);
section.SectionInformation.ProtectSection
(“RsaProtectedConfigurationProvider”);
config.Save(ConfigurationSaveMode.Modified);
}
private void UnProtectSection(string sectionName)
{
Configuration config = WebConfigurationManager.OpenWebConfiguration
(Request.ApplicationPath);
ConfigurationSection section = config.GetSection(sectionName);
section.SectionInformation.UnprotectSection();
config.Save(ConfigurationSaveMode.Modified);
}
private void BindSections()
{
Configuration config = WebConfigurationManager.OpenWebConfiguration
(Request.ApplicationPath);
List<SectionInformation> colSections = new List<SectionInformation>();
foreach (ConfigurationSection section in
config.SectionGroups[“system.web”].Sections)
colSections.Add(section.SectionInformation);
grdSections.DataSource = colSections;
grdSections.DataBind();
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<title>Encrypt Config</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:GridView id=”grdSections” DataKeyNames=”SectionName” AutoGenerateColumns=”false”
OnRowCommand=”grdSections_RowCommand” Runat=”server” >
<Columns>
<asp:ButtonField ButtonType=”Link” Text=”Protect” CommandName=”Protect” />
<asp:ButtonField ButtonType=”Link” Text=”UnProtect” CommandName=
UnProtect” />
<asp:CheckBoxField DataField=”IsProtected” HeaderText=”Protected” />
<asp:BoundField DataField=”SectionName” HeaderText=”Section” />
</Columns>
</asp:GridView>
</div>
</form>
</body>
</html>

When you click the Protect link, the grdSection_RowCommand() event handler executes and calls the ProtectSection() method. This method calls the SectionInformation. ProtectSection() method to encrypt the selected section. Notice that the name of a ProtectedConfigurationProvider is passed to the ProtectSection() method.

The page in Listing saves the configuration file. By default, the ASPNET and NETWORK SERVICE accounts do not have permission to write to the file system. If you want the page in Listing 28.26 to execute within the security context of the user requesting the page, then you can enable per-request impersonation by adding the configuration file in Listing to the root of your application.

Deploying Encrypted Web Configuration Files
If you need to copy an encrypted configuration file from one server to a new server, then
you must copy the keys used to encrypt the configuration file to the new server. Otherwise,
your application can’t read encrypted sections of the configuration file on the new server.

You can’t copy an encrypted configuration file from one server to another when you are using the DpapiProtectedConfigurationProvider. This section assumes that you are using the RsaProtectedConfigurationProvider. By default, the RsaProtectedConfigurationProvider uses a public/private key pair stored in a key container named NetFrameworkConfigurationKey. This key container is located at the following path:
\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys

If you want to deploy an application that contains an encrypted configuration file to a new server, then you must configure a new key container and import the key container to the new server. You must complete five configuration steps:

1. Create a new key container.
2. Configure your application to use the new key container.
3. Export the keys from the origin server.
4. Import the keys on the destination server.
5. Grant access to the key container to your ASP.NET application.

You need to perform this sequence of configuration steps only once. After you have set up both servers to use the same encryption keys, you can copy ASP.NET applications back and forth between the two servers and read the encrypted configuration sections. Let’s examine each of these steps one by one.

First, you need to create a new key container because the default key container, the NetFrameworkConfigurationKey key container, does not support exporting both the public and private encryption keys. Execute the following command from a command prompt:
aspnet_regiis -pc “SharedKeys” –exp

This command creates a new key container named SharedKeys. The -exp option is used to make any keys added to the container exportable. After you create the new key container, you must configure your application to use it. The web configuration file in Listing configures RsaProtectedConfigurationProvider to use the SharedKeys key container.

LISTING Web.config
<configuration>
<configProtectedData
defaultProvider=”MyProtectedConfigurationProvider”>
<providers>
<add name=”MyProtectedConfigurationProvider”
type=”System.Configuration.RsaProtectedConfigurationProvider” cspProviderName=””
useMachineContainer=”true” useOAEP=”false” keyContainerName=”SharedKeys” />
</providers>
</configProtectedData>
<connectionStrings>
<add name=”Movies” connectionString=”Data Source=DataServer;Integrated Security=true;
Initial Catalog=MyDB” />
</connectionStrings>
</configuration>

Notice that the configuration file in Listing includes a configProtectedData section. This section is used to configure a new ProtectedConfigurationProvider named MyProtectedConfigurationProvider. This provider includes a keyContainerName attribute that points to the SharedKeys key container. The next step is to export the keys contained in the SharedKeys key container to an XML file. You can export the contents of the SharedKeys key container by executing the following command:
aspnet_regiis -px “SharedKeys” keys.xml –pri

The final step is to grant access to the key container to your ASP.NET application. By default, a page served from Internet Information Server executes within the security context of either the NT Authority\NETWORK SERVICE account (Windows 2003 Server or Vista) or the ASPNET account (other operating systems). You can grant access to the SharedKeys key container to the ASPNET account by executing the following command:
aspnet_regiis -pa “SharedKeys” “ASPNET”

Executing this command modifies the ACLs for the SharedKeys key container so that the ASPNET account has access to the encryption keys.After you complete this final step, you can transfer ASP.NET applications with encrypted configuration files back and forth between the two servers. An application on one server can read configuration files that were encrypted on the other server.As an alternative to using the aspnet_regiis tool, you can transfer encryption keys with the help of the RsaProtectedConfigurationProvider class. The RsaProtectedConfigurationProvider class contains methods for exporting and importing keys to and from XML files programmatically.

No comments:

Post a Comment