Halt!  Who goes there?
Securing your precious online assets with Active Server Pages


by Jason Salas, KUAM.COM
September 23, 2001

 

Past editions:

Error Handling in VBScript

Creating a banner ad rotation system

The Web-safe color palette for developers

Time-saving Windows shortcuts

Analyzing your site's traffic logfiles

I was talking recently with a friend of mine who is the Webmaster for a local wireless services company, who was asking about securing files within a directory using Active Server Pages. This is rather timely, seeing as how our military bases have increased their security for people accessing resources within.  So, I'm going to take a variation on a theme and show you how you can implement a password-protection system on your own Website, and have it up and running in less than 5 minutes. Really!

WindowsNT and Windows 2000 ship with the Challenge/Response method, which provides about as much protection for you precious files as possible. Requiring authentication of this type is known as system-level security. When a user attempts to access resources contained within a protected directory, he is greeted with the following window, which challenges him for authentication information (typically in the form of a Username and Password).


The standard login window from WindowsNT and Windows 2000 Challenge/Response security login method


A failed login attempt, typically because of an error in the authentication information

If the user enters the authentication information correctly, he is granted access to the directory. If not, he is either presented a screen letting him know authentication failed, or on more progressive sites, he is redirected to another page. That's what we'll be doing, but by implementing the password protection with page-level security, by storing the intended values within the page. And because ASP performs its processing instructions on the server, and returns only outputted HTML, we don't run the risk of a more sophisticated user viewing the source code and accessing our secretive login information.


The login challenge window we're going to build


Our login system after failing authentication

Our password-protection system works in a similar fashion by challenging the user for a username and password, by visiting the page INDEX.ASP. If he has the right combination, he accesses a sample page with some content on it. Should he fail authentication, he will be redirected back to INDEX.ASP and presented with an error message letting him know something went wrong.

For starters, we'll be using VBScript as our server-side processing language. This is declared at the top of the page. Next, we'll build a simple Web form containing three main elements: (1) a textbox to hold the username, (2) a password box to hold the value of the password, and (3) a submission button to process the form. Note how we use the value of <input type="password"> for the password box to ensure that anything entered into it isn't readable, being displayed as a series of stars. Next, we include some server-side processing…and this is where the real fun begins. Within the Value attribute of the textbox for the Username, we include the statement
<%= Request("USERNAME") %>. This will be used to automatically insert the Username value the user enters if the page fails authentication, to save time.

Further down the page we insert an If statement that will display a custom error message f the user fails authentication. Note how we're using just Request instead of
Request.Form or Request.QueryString. This extracts the value of either collection and will be critical to making the login process work, because we'll be extracting values from the querystring of the URL, but submitting the form using the POST method. If we passed all of the values through POST, we couldn't extract them from the URL upon postback…and likewise, if we submitted the form using GET, we would expose the user's login information (his username and password) in the URL itself. And this would defeat the purpose of providing security.

Copy the following code and save it as INDEX.ASP:

INDEX.ASP
Download the source code for this tutorial

<%@ Language=VBScript %>
<HTML>
<HEAD>
<META name="robots" content="noindex,nofollow">
<BODY><h2><font face="tahoma"><p align="center">Login to the system so that you access the confidential information...</p>
<hr size="2" width="85%"></h2>
<P>
<form action="secured.asp" method="post">
<center>
<table>
<tr>
<td>Username: </td>
<td><input type="text" size="15" name="USERNAME" value="<%= Request("USERNAME")%>"></td>
</tr>
<tr> 
<td>Password: </td>
<td><input type="password" size="15" name="PASSWORD"></td>
</tr>
<tr>
</td></td> 
<td align="right"><input type="submit" value="Next &gt;"></td>
</tr> 
</table> 
</center>
</form></font>
<% If Request("failedlogin") = "true" Then %> 
<font face="tahoma" color="teal"><h4><P align="center">The username or password you supplied was invalid.</h3></font></P>
<% End If %>
</P>
</BODY>
</HTML>

Now, we'll build the sample page that is to be protected. There's nothing really nothing special going on, and I threw some generic text in just to be fancy. In actuality this would function as a splash page with providing navigation and more links to other pages within the site. However, the top line of the code reveals that we'll be referencing a server-side include (SSI) which will contain a script that will evaluate the login information and either let the user access the page, or kick him back to INDEX.ASP.

Copy the following code and save it as
SECURED.ASP:

SECURED.ASP
Download the source code for this tutorial

<!--#include file="login-challenge.asp"-->
<HTML>
<HEAD>
<META name="robots" content="noindex,nofollow">
<BODY>

<P align=center><h1 align=center><FONT face=Tahoma size=5>This page should 
contains private content!&nbsp; You should not be able to browse to this 
page...but get in through proper authentication.</FONT> 

</BODY>
</HTML>

Now we'll really get into the magic of our application by building the include file itself. The file is merely an Active Server Page that contains only script code, which will extract the values of USERNAME and PASSWORD from the form fields in INDEX.ASP. It will then compare this data to hard-coded values (in this case, a username value of "guest" and a password value of "opensaysme"), and if it does not match, redirect the user to INDEX.ASP, where he'll be presented with the error message we defined. Just for safety's sake, I tell the script to output a single carriage-return just in case anyone tried to browse directly to this file by typing the full path in the browser. Notice how we hard-code into the filename to redirect the user two parameters within the querystring itself, a failedlogin value of true, and the value of USERNAME. This will satisfy the condition for the error message If statement we defined in INDEX.ASP.

Copy the following code and save it as
LOGIN-CHALLENGE.ASP:

LOGIN-CHALLENGE.ASP
Download the source code for this tutorial

<%
If (Request("USERNAME") <> "guest") Or (Request("PASSWORD") <> "opensaysme") Then
Response.Redirect("index.asp?failedlogin=true&USERNAME=" & Request("USERNAME")) 
End If
Response.Write Chr(13) ' prints out a carriage return as output in case the page is browsed to directly
%>

You've got it - a simple system that makes sure you're files are safe from prying eyes! Make sure to copy or transfer all of your files onto your Web server and then browse to INDEX.ASP. Try to break it by entering erroneous login information, and try browsing to each SECURED.ASP and LOGIN-CHALLENGE.ASP directly. You won't get there, meaning your pages are safe! Now, if you want to apply this protection to other files in the same or other directories on your Web server, you merely have to insert the SSI include statement at the top of each page.

By storing all of the critical information in our SSI include file, you make site management easier on yourself. My
USERNAME and PASSWORD values are centrally stored, so if I ever needed to change either of their values, I would do so only in LOGIN-CHALLENGE.ASP, and the rest of the pages would dynamically reflect the new login sequence, because they all reference the code contained with the include file. The alternative, hard-coding the USERNAME and PASSWORD into each and every file you want protected is possible, but you'd have to painstakingly change each and every page that contained the login sequence. This would be hard if you protected more than 10 pages!

You might have noticed that I also coupled my security by making sure that search engines and search directories don't crawl our pages and wind up listing them in their indexes. It would be counterproductive if we had our pages someday show up on Yahoo! and Google, as the result of a Web search. To prevent this, we include META data  (which is information about information) within the
<HEAD> tags of our pages.
<META name="robots" content="noindex,nofollow">

Just remember that in lieu of being able to access the server controls directly, like if you use a third-party Web hosting company to store your pages, this is a quick, easy, and very effective way of protecting your resources from intrusion.

Have fun using this in your own projects!