|
One of the most anticipated features in ASP.NET 1.x was the forms authentication system.
Web developers were no longer forced to roll their own authentication solutions when building web
applications. The only real shortcoming in the system was that it didn't protect
non-ASP.NET files. If you needed to secure PDF or image files, you were pretty much out of luck.
While the inclusion of a number of login controls made forms authentication easier to
implement in ASP.NET 2.0, we'd still be forced to look elsewhere
to secure files coming directly from the file system... or so it seemed.
As it turns out, if you're using IIS 5 or later you actually can use the ASP.NET authentication system
to secure other types of files. It's not setup by default and has some limitations if
you're using IIS 5, but you can do it and I'm going to show you how.
The Scripts and Files Involved
Before we get to the configuration steps that you'll need to do, let's examine the scripts and other files
involved. I'll start with our web.config file.
<?xml version="1.0"?>
<configuration>
<system.web>
<authentication mode="Forms">
<forms loginUrl="login.aspx" defaultUrl="default.aspx" />
</authentication>
</system.web>
<location path="secure">
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>
</configuration>
It's relatively short and simple. In it I indicate that we'll be using forms authentication and specify
the location of the login script ("login.aspx"). I then indicate that anonymous users are to be denied
access to the sub-folder named "secure".
Next let's take a look at our login script.
<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
Sub btnLogin_OnClick(ByVal Src As Object, ByVal E As EventArgs)
If (txtUsername.Text = "john" And txtPassword.Text = "pass") Then
FormsAuthentication.RedirectFromLoginPage(txtUsername.Text, True)
End If
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Login</title>
</head>
<body>
<form id="myForm" runat="server">
<div>
Username:
<asp:TextBox ID="txtUsername" runat="server" /><br />
Password:
<asp:TextBox ID="txtPassword" TextMode="password" runat="server" /><br />
<br />
<asp:Button ID="btnLogin" runat="server" Text="Login" OnClick="btnLogin_OnClick" />
<p>
The login is "john" and the password is "pass".
</p>
</div>
</form>
</body>
</html>
Nothing too fancy going on here either. The page contains a couple of textboxes for the user to enter their login and password,
a button to submit the form, and an event handler for the button's OnClick event. For simplicity, the code simply
compares the entered information to some hard-coded text values and if the values are correct then the user is authenticated.
That's it.
The only other file involved is our index page ("default.aspx") which can be seen here.
<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Default Page</title>
</head>
<body>
<form id="myForm" runat="server">
<div>
<p>
Logged in as: "<asp:LoginName ID="myLoginName" runat="server" />"
- <asp:LoginStatus ID="myLoginStatus" runat="server" />
</p>
<p>
This image is secure:
</p>
<a href="secure/winxp.gif"><img src="secure/winxp.gif" border="0" /></a>
<p>
<strong>Note:</strong> After clicking "Logout" link above, the
image may still be visible due to browser caching. If you click the
refresh button (F5) in your browser or clear the cache then the image
will once again appear as a broken image (as it should when you're not
authenticated).
</p>
</div>
</form>
</body>
</html>
Again there's nothing fancy here... just a simple page that shows you who you're logged in as, provides
a link to the login page, and displays an image from the secured directory. The point is that when you're
not logged in the image won't load and you'll get the broken image placeholder, but once you log in the
image will load fine. The image in question is simply the Windows XP logo that is shown by default on XP's
IIS welcome page. I used it only because it was handy and I was too lazy to come up with and create some
really cool image to use. Feel free to pretend that it's the coolest image you've ever seen. ;)
So here's what our little application looks like:
Configuring IIS
So far all we've done is set up the authentication. If you browse to the application now,
it'll run fine and you'll be able to log in and log out, but the image file will load either way.
The goal of all this is to secure the image file and the way you do that is by tricking IIS into
thinking it's something to be processed.
Configuration will vary depending on if you're using IIS 5.x or IIS 6, but the screen shots below
are from IIS 5.1 on my XP box. I'll discuss a few differences that you'll encounter when using IIS 6
afterwards.
-
Launch the IIS management console. You can find it in the "Administrative Tools" folder in
the system's Control Panel. On XP, it's simply called "Internet Information Services".
-
Navigate to the folder or application for which you want to enable protection of other file types
and bring up the "Properties" dialog box by right clicking on the folder and choosing
"Properties" from the context menu.
-
If your folder is not already an application, click the "Create" button
in the "Application Setting" area of the "Directory" tab.
-
Now click the "Configuration..." button to bring up the "Application Configuration"
window.
-
Once there, make note of the path to the DLL that .NET is using to do the processing
for it's file extensions (like .aspx, .asax, .master, .config, etc.).
It should be something like:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll
-
Now we're going to add a new application mapping for the type of file you're trying to protect.
In this case we're using .gif image files.
Still on the "Mappings" tab of the "Application Configuration" window,
click the "Add" button to bring up the "Add/Edit Application Extension Mapping" window.
In the "Executable" field enter the path to the DLL you made note of earlier.
In the "Extension" field enter the extension for the type of files you want to protect -- in this case
".gif".
When you're finished, click the "OK" button. Close the remaining dialog boxes and exit the
IIS management console.
That's the process for IIS 5.x. In IIS 6 you can use what are called "Wildcard Application Maps"
to avoid needing to set up the mapping for every extension you want to protect. Simply add the DLL whose
location you made a note of earlier as a wildcard application map and it'll handle all extensions.
Another major shortcoming in IIS 5.x is that you can only use this method to protect static files.
Other script files (like classic ASP scripts) won't execute when set up this way. When using
wildcard application mapping on IIS 6, once ASP.NET has handled authentication, processing is passed
back to IIS and then to whatever other handler is mapped to the file's extension. Because of this,
if you're hosting on IIS 6 you actually can protect classic ASP scripts and other
types of dynamic content using ASP.NET authentication.
The Protection in Action
When you first launch the application you should see something like this:
Notice that there's no name specified in the LoginName control and the image won't load.
Even if you try and request the image directly it won't load and you'll be redirected to the login page.
Once you visit the login page and log in, the page will look something like this:
Conclusion
While it does have some shortcomings (especially on IIS 5.x), this method of securing
non-ASP.NET files can be extremely useful. When compared to the alternatives of a
third party component or building your own solution from scratch this method starts to look pretty
good indeed.
More information:
Securing Non-ASP.NET Files from the ASP.NET QuickStart Tutorials
Using Forms Authentication in ASP.NET - Part 1
Using Forms Authentication in ASP.NET - Part 2
Protecting Files with ASP.NET from 4GuysFromRolla
|