Jan. 13, 2011, 1:19 a.m.
posted by edward
One of the downsides of File Authorization is the maintenance of the ACLs on the resources that you want to protect. ACLs are frequently lost when using FTP to transfer files to a Web site. ACLs also have a sometimes-confusing inheritance model that, for a large site, can cause maintenance headaches. ASP.NET provides URL Authorization as a way to authorize users by attaching role information to URLs within a Web site. This URL to Role mapping is done in the web.config file. The URL Authorization module uses the <authorization> element to store this mapping. You saw this earlier in the web.config file used in Listing 7.3. The authorization element can contain both allow and deny elements. Both allow and deny elements have a users attribute, a roles attribute, and a verb attribute. Each attribute will accept a comma-separated list of items. The users attribute is used to match identities. There are two special identities. The "*" identity is used to represent all users. The "?" is used to represent anonymous users.
Before evaluating the authorization element, a merged authorization list is created by taking the authorization list from all of the applicable .config files, including the machine.config file. This merged list is then evaluated from the top to the bottom. Let's look at some examples.
<authorization> <deny users="?"/> </authorization>
This is a fragment from the web.config in Listing 7.3. What this says is that I want to deny all anonymous users—"?" means anonymous users. But if I am denying all anonymous users, don't I have to allow authenticated users? As it turns out, no. Remember that the preceding list is merged with machine.config at the very least. Machine.config by default contains the following fragment:
<authorization> <allow users="*"/> </authorization> Which means that the merged list during evaluation will look like: <authorization> <deny users="?" /> <allow users="*" /> </authorization>
The first deny users makes sure that no anonymous users are allowed in. The second allow users says that everyone is allowed, which means everything other than anonymous users in this case, meaning only authenticated users. Let's take a look at another fragment.
<authorization> <allow roles="BUILTIN\Administrators" /> <deny users="*" /> </authorization>
What does this do? Can you guess? Remember top to bottom evaluation. The first element says that if the Principal is a member of the built-in Windows NT group Administrators, I should be allowed access. If I am not a member of this group, the next element takes effect, denying anyone else. You may wonder why the <allow users="*"/> in machine.config doesn't still let everyone in. When the list is merged, conflicting rules are ordered based on which one is contained within a .config file that is "closer" to the page being requested. Because the web.config is "closer" to the page than the machine.config, the <deny users="*"/> element overrides the <allow users="*"/>. Let's try one more:
<authorization> <allow users="sa" roles="BUILTIN\Administrators, KINSMAN\Publishers" /> <deny users="*" /> </authorization>
In this case, the one allow element is doing a lot of work. It says that if I am logging in with an account called "sa" or a Principal with the "BUILTIN\Administrators" role or a Principal with the "KINSMAN\Publishers" role, I am granted access. Anyone else is denied access.
The authorization element that we have looked at so far applies to the Web site as a whole. In many cases I might want to apply different authorization elements to different parts of the URI namespace. The location element provides a way to do this. The location element allows the developer to specify a different set of settings for a subset of the URI namespace. The location element has two attributes. The first, path, indicates what part of the namespace the settings apply to. The second, allowOverride, can be set to false to prevent another web.config lower in the hierarchy from overriding the settings contained within the location element.
Let's take a Web site that has a need to secure three paths. The http://www.deeptraining.com/attendees path should be available only to people in the attendee, publisher, or administrator roles. The http://www.deeptraining.com/publish path should be available only to people in the publisher or administrator roles. Finally, the path http://www.deeptraining.com/admin should be available only to users in the administrator role. The web.config in Listing 7.10 shows a way to do this using the location element.
Listing 7.10 A web.config That Uses the Location Element to Specify Different Authorization Requirements for Different Directories
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.web> <authentication mode="Forms"> <forms name="FORMURL" loginUrl="login.aspx" protection="All" timeout="30" /> </authentication> <authorization> <allow users="*" /> </authorization> </system.web> <location path="admin"> <system.web> <authorization> <allow roles="Administrator" /> <deny users="*" /> </authorization> </system.web> </location> <location path="publish"> <system.web> <authorization> <allow roles="Administrator" /> <allow roles="Publisher" /> <deny users="*" /> </authorization> </system.web> </location> <location path="attendees"> <system.web> <authorization> <allow roles="Administrator" /> <allow roles="Publisher" /> <allow roles="Attendees" /> <deny users="*" /> </authorization> </system.web> </location> </configuration>
Note that I allow all users to access the root of the application. At the very least, I must allow all users to access the login.aspx form, which happens to reside in the root. If you don't want users to be able to access the root in an unauthenticated fashion, create a location element specifically to allow access to login.aspx, like this: