Wednesday, July 16, 2008

Creating a user authentication (Login) area in ColdFusion

Creating a user authentication (Login) area.

A lot of users are always asking me how they can create a way on their web site that is only allowed to be used by registered users. This is called "User Authentication (Member's Only)" and can be created easily with ColdFusion.
The first thing that you must do is to create a table in your database called "tblAdmins".
Create the following fields in the database table:
Field Name Type
user_id AutoNumber
user_name text
user_pass text
This is where you will have your users login data be default, this will allow you a "location" to verify against.
You will need to create and ODBC connection for this database, to create an ODBC data source, simply open up your ColdFusion administrator (http://127.0.0.1/cfide/administrator/) or contact your ISP. Call the ODBC "userLogin".
This tutorial will require 4 pages to be created.
- Application.cfm
- login.cfm
- login_process.cfm
- members_only.cfm
The first page that will need to be created is titled "Application.cfm". One thing you must keep in mind with this file, is that it will always be execute before any ColdFusion (.cfm) file. Think of this as the page where you can define things and/or check for things. This will always run before any page, so this is a great place to check to see if a user is logged in. So naturally, this is the place we're putting the following code on :)
Within this page you will create the following code:
<!--- Create the application --->
<cfapplication name="MyApp" clientmanagement="Yes"
sessionmanagement="Yes"
sessiontimeout="#CreateTimeSpan(0,0,15,0)#"
applicationtimeout="#CreateTimeSpan(0,2,0,0)#">
<!--- Now define that this user is logged out by default --->
<CFPARAM NAME="session.allowin" DEFAULT="false">
<!--- Now define this user id to zero by default, this will be used later on to access specific information about this user. --->
<CFPARAM NAME="session.user_id" DEFAULT="0">
<!--- Now if the variable "session.allowin" does not equal true, send user to the login page --->
<!---
the other thing you must check for is if the page calling this application.cfm is the "login.cfm" page
and the "Login_process.cfm" page since the Application.cfm is always called, if this is not checked
the application will simply Loop over and over. To check that, you do the following call
--->
<cfif session.allowin neq "true">
<cfif ListLast(CGI.SCRIPT_NAME, "/") EQ "login.cfm">
<cfelseif ListLast(CGI.SCRIPT_NAME, "/") EQ "login_process.cfm">
<cfelse>
<!--- this user is not logged in, alert user and redirect to the login.cfm page --->
<script>
alert("You must login to access this area!");
self.location="login.cfm";
</script>
</cfif>
</cfif>

[NOTE: I updated the code above, because a lot of people were having problems implementing it because they did not understand how CGI.SCRIPT_NAME works. This will resolve those issues and should work AS IS in all cases - Pablo]
That is all you need in the Application.cfm page. I'll explain the items as best as possible:
The first thing you created was the "cfapplication". This command creates the ability to track users, create session variable and much more. This is needed to keep order within the application. One crucial section of this tag is the value you specify on "sessiontimeout". This is the time that that specifies how long the user will be logged as "Loggedin" before having to re login. This time is only counted if the user does nothing. If your pages are small and do not require large amounts of reading, then 15 minutes should be enough time. However, if your pages contain a lot of text and require lots of reading, then you might have to increase the time specified. The CreateTimeSpan values are as follows:

#CreateTimeSpan(days,hours,minutes,seconds)#

The next thing you created was a <cfparam>. What the <cfparam> does is to define a value for a variable if (and only if) that variable doesn't already exist. If that variable does exist, it simply does nothing.

The last thing you created was a way to check on all page to make sure that the user is correctly logged in. It simply checks for a session variable called "session.allowin". If this variable has a value of "TRUE" then that user is logged in, if that variable has a value other than "TRUE" (i.e. "FALSE") then this user is not logged in, send them to the login page.
The next step in this tutorial is the "login.cfm" page.
This page is simply HTML, it doesn't really require any Coldfusion code, here is what it must have:
<form action="login_process.cfm" method="post">
Username: <input type="text" name="user_name" value=""><BR>
Password: <input type="password" name="user_pass" value=""><BR>
<input type="submit" name="login_user" value="Log In"><BR>
</form>
The login page, will submit the form to the "login_process.cfm" page. That page however, is where the magic takes place. I'll create the entire page, and then come back and explain it.

<!--- Get all records from the database that match this users credentials --->
<cfquery name="qVerify" datasource="userLogin">
SELECT user_id, user_name, user_pass
FROM tblAdmins
WHERE user_name = '#user_name#'
AND user_pass = '#user_pass#'
</cfquery>
<cfif qVerify.RecordCount>
<!--- This user has logged in correctly, change the value of the session.allowin value --->
<cfset session.allowin = "True">
<cfset session.user_id = qVerify.user_id>
<!--- Now welcome user and redirect to "members_only.cfm" --->
<script>
alert("Welcome user, you have been successfully logged in!");
self.location="/members_only.cfm";
</script>
< cfelse>
<!--- this user did not log in correctly, alert and redirect to the login page --->
<script>
alert("Your credentials could not be verified, please try again!!!");
self.location="Javascript:history.go(-1)";
</script>
</cfif>
That is all that I needed on this page. What you're basically doing is as follows:
First you are making a connection to the database with the username/password the user typed in on the "login.cfm" page. You are making a call to the database to look in the "tblAdmins" table for a user with this combination of username/password. if a match is found, then you have a record, if no matches are found, then there are no records.

The next step is to do a <cfif> to see if any records were found. If a record was found, then this user is good, go ahead and log them in. if there are no matches, then this user is no good, keep him out of the members only section.
if the user was good, then you overwrite the existing value of the "session.allowin" variable to "TRUE". Remember that the "Application.cfm" is checking for this value to be anything other than true to make the user log in. Since this now has a value of "TRUE" the user is logged in and therefore, does not need to login once again.
The last page you must create is the "members_only.cfm". This can be anything you want, this is the content that the user is logging in for, so make it good :)

No comments: