
January 13, 2004
Get
the code here!
Introduction
An easy way to organize your protected resources within your Web site is to
place them in their own subdirectory beneath the application root. The process of customizing configuration for a subdirectory
is simple enough, however a few common misunderstandings are encountered along
the way, which can lead developers to take the wrong path. This article explains
how to set up your directory structure, where to place your files, and how you
can define your configuration settings.
Configuration Inheritance
At runtime when an ASP.NET application resource is requested, its virtual
directory path (through IIS) is used to gather a hierarchical collection of
configuration files. This starts with machine.config, which configures your
entire Web server (actually, the entire .NET Framework runtime environment), then looks into the root of the Web application and its subdirectories for web.config
files that may contain modifications to this default configuration.
There are no security settings within the machine.config file (by default)
so to secure any resources, so you typically take care of this within the web.config
for the Web application, and possibly within a web.config placed in a protected subdirectory of the same application. First you have to have forms authentication
enabled for the application which is handled in the application root's web.config. Then, to protect resources in subdirectories you can either place a web.config file in a protected subdirectory to reject anonymous users for all resources in that subdirectory, or use the <location> tag in the application's web.config to do achieve the same result.
Subdirectory Web.Config
The web.config file in the sample application enables forms authentication for the
application, and allows anonymous user access all resources. The subdirectory
\articles holds protected files, so the web.config file beneath \articles includes
an <authorization> section rejecting anonymous users.

When a resource in \articles is requested, the login form from the application
root is presented.

When the user clicks the Login button, the following code validates user input,
and authenticates the user before redirecting to the requested resource:
if ((this.UserName.Text == "user1" || this.UserName.Text == "user2" ) && this.Password.Text == "password") { System.Web.Security.FormsAuthentication.RedirectFromLoginPage(this.UserName.Text , false); }
Of course, you’ll probably have a more sophisticated database lookup
in a real-world application, but there’s the basic process.
What’s the Big Deal?
There are a number of common errors committed in setting up this architecture.
The first is placing the <authentication> section enabling forms authentication
in the subdirectory’s web.config file. This causes a configuration parsing
error as shown here:

This is because the <authentication> section is only supported in IIS
application directories, which doesn't include subdirectories of an IIS application. So the second common mistake is creating an application
directory of the subdirectory in question, as demonstrated in the next diagram:

This is when the next set of configuration problems surface. First, the login
page must be correctly referenced in the subdirectory’s web.config file.
For example, you can reference the application directory using a relative URL:
<authentication mode="Forms"> <forms loginUrl="../login.aspx" timeout="2"> </forms> </authentication>
After the user is properly authenticated, another potential error arises from
the fact that this subdirectory is now an IIS application. ASP.NET is now unable
to find the compiled codebehind classes for the subdirectory’s Web forms,
as shown in this error:

Since the subdirectory is now an IIS application, it is looking for a \bin
directory beneath it where compiled classes can be found for the application.
Since this doesn’t exist, an error occurs. The solution to this, of course,
is to configure the authentication process correctly, as described at the beginning
of this article.
- Enable forms authentication in the root application directory’s
web.config, and
- In protected subdirectories, place a web.config with the <authorization> section required
to prevent access.
Placing web.config files beneath subdirectories that require custom configuration apart from the base application configuration, makes it possible to clearly distinguish configuration settings for different directories. The drawback of this is in configuration parsing, since now the runtime must retrieve the maching.config, the application web.config and the hierarchy of subdirectory web.config files when resources are requested. There is an alternative removing some of this overhead.
Location, Location, Location
A second, and preferred approach that also works is to use the <location> element in
the application web.config file, to specify different settings for subdirectories.
This removes the need to place another web.config file in the protected subdirectory,
and allows the root to control all settings from a single web.config file.
To try this out, in the code sample for this application, change the application
web.config file by adding the following section within the <configuration>
root:
<location path="articles"> <system.web> <authorization> <deny users="?" /> </authorization> </system.web> </location>
Go ahead and rename the web.config within the /articles subdirectory, and you’ll
see the same results. Your login page is presented when accessing resources in
that subdirectory.
Now, after you’ve seen that work, edit your web.config file again in
the /articles subdirectory, to the following:
<authorization> <allow users="*" /> </authorization>
Notice that the login page will no longer be presented! That’s because your
subdirectory’s web.config is considered to override settings in the application
directory (its parent).
Comments on the <location> approach:
- Can control configuration from a single web.config for the application
- Means that fewer hierarchical configuration files to collect to access a
resource, thus less overhead requesting the resource (the first time, since
it is cached after that)
- Can deny subdirectory web.config overrides
Comments on subdirectory web.config settings:
- Can allow divided development efforts to control their own configuration
requirements
- Application will fail if overrides are rejected by <location> settings
with the following:
<location path="articles" allowOverride="false">
If you change the application web.config to use the allowOverride attribute, you’ll
see something like the screenshot below:

Authors
 |
Michele is a Chief Architect with IDesign, Microsoft Regional Director for San Diego, Microsoft MVP for Web Services and a BEA Technical Director. In addition, Michele is a member of the board of directors for the International Association of Software Architects (IASA). At IDesign Michele provides high-end architecture consulting services, training and mentoring. Her specialties include architecture design for robust, scalable and secure .NET architecture; localization; Web applications and services; and interoperability between .NET and Java platforms. Michele is a member of the INETA; a frequent conference presenter at major technology conferences such as Tech Ed, PDC, SD and Dev Connections; conference chair for SD’s Web Services track; and a regularly published author. Michele’s next book is Windows Communication Framework Jumpstart for O’Reilly, due out in early 2006. Reach her at www.idesign.net or visit her blog at www.dasblonde.net.
|
|