Somebody Get Me Out of This CacheH2 P class

Team-Fly    

ColdFusion® MX: From Static to Dynamic in 10 Steps
By Barry Moore
Table of Contents
Step 9.  User Security


Types of Security

In the past, all the building blocks to create application security were there in ColdFusion, and developers went about developing their own custom systems to implement security. When it comes to dealing with users, there are two basic types of security: authentication and authorization.

Authentication deals with verifying who a user is. We need some way to verify that a user trying to access secure areas of our site is in fact who he claims to be. This is typically accomplished with a "what you know" type of approach. That is, if you really are who you say you are, you should know what password is stored against your username. If you don't know that, you are probably not who you claim to be. This is not a foolproof system, of course, but it is adequate in many instances.

Authorization deals with verifying what a user is allowed to do. After we have authenticated a user, we need to worry about authorization. Authorization deals with making sure that a user performs only those actions that he is allowed to perform. For example, let's say we allow two users to log in to our secure web site. User 1 is pretty bright, so we might give her the capability to change everything throughout the site. We are not so sure about User 2, so we might only give him the capability to edit information but not to insert new information or delete existing information. We now have users with two different levels of authorization. They are both allowed to log in (authentication), but one is authorized to delete items and one is not.

Authentication

Many custom-built authentication systems revolve around storing a user's credentials somewhere (like a database) and then having individual users log in through a form. The form information is then compared to the data stored in the database.

If the credentials don't match, the user is denied access. If they do match, the user is allowed access and is usually identified through the use of variables stored in a shared memory scope, such as the Session scope. By storing the user's information in the Session scope, we are able to maintain state for that user for as long as the session variables last. For example, if we have checked a user's credentials and are satisfied that they match, we could use the following code to store his information in his particular Session scope.

 <CFLOCK SCOPE="SESSION"          TIMEOUT="10"          THROWONTIMEOUT="Yes"          TYPE="EXCLUSIVE" >     <CFSET SESSION.UserLoggedIn="True">     <CFSET SESSION.UserNanme="#FORM.UserName#">  </CFLOCK>

Later, if we want to restrict access, we could simply use an IF statement (like the following one) in our Application.cfm file or at the top of a page we would like to secure.

 <CFLOCK SCOPE="SESSION"          THROWONTIMEOUT="Yes"          TYPE="READONLY"          TIMEOUT="10">        <CFIF SESSION.UserLoggedIn NEQ "True">              <CFLOCATION URL="LoginForm.cfm" ADDTOKEN="No">        </CFIF>  </CFLOCK>

In the preceding code, we are locking the SESSION scope and then reading the value of the SESSION.UserLoggedIn variable. If it is not equal to TRUE, we redirect the user to the login form. If you include this code in an Application.cfm file for a particular subdirectory, the code would be included at the top of every page in that directory, thus securing every page in that directory. In this particular case, however, you would need to have your login form outside the secured directory. Otherwise, the code from the Application.cfm file would be included at the top of the login form as well, which would redirect us to the login form, which would again redirect us to the login form and put us into an infinite loop. To avoid this situation, we could also use the <CFABORT> tag, which will be discussed later in this step.

The user's session variables would last until that user logs out or the time span for the session variables expires. To log a user out, you simply get rid of the session variable or change its value. In our case, we could simply use the following code to log our user out.

 <!--- link to the logout page --->  <A HREF="Logout.cfm">Log Out</A>  <!--- code in the Logout.cfm page --->  <CFLOCK SCOPE="SESSION"          TIMEOUT="10"          THROWONTIMEOUT="Yes"          TYPE="EXCLUSIVE" >     <CFSET SESSION.UserLoggedIn="False">  </CFLOCK>

NOTE

Because our code checks to see if SESSION.UserLoggedIn="True" rather than IsDefined(SESSION.UserLoggedIn), we have to make sure that variable exists before we try to check it. To do this, we could include the following code in our Application.cfm file:

 <CFLOCK SCOPE="SESSION"          TIMEOUT="10"          THROWONTIMEOUT="Yes"          TYPE="EXCLUSIVE" >     <CFPARAM NAME="SESSION.UserLoggedIn" DEFAULT="False">  </CFLOCK>

That way, if the variable did not exist, we would create it and set its value to False.


NOTE

For more information on Session variables, see Step 8, "ColdFusion Application Framework."


Authorization

After we have established a user's identity (authentication), we might want to restrict that particular user's rights within the application. To do this, developers usually create roles or groups to which users will belong. For example, we could have several roles for our users, such as Author, Editor, and Administrator. These roles would each have access to different levels of functionality throughout the site. Table 9.1 illustrates some hypothetical roles and the actions users with those roles could perform.

Table 9.1. Examples of User Roles

Role

Authorization

Author

Authors can create new content. They can also edit their own content but cannot edit the content of other users.

Editor

Editors can do everything that Authors can do and can also edit the work of other users.

Administrator

Administrators can do everything that Authors and Editors can do and can also delete content from any user.

To track which role(s) a user belongs to, we could simply add another session variable to the user's session, as follows:

 <CFLOCK SCOPE="SESSION"          TIMEOUT="10"          THROWONTIMEOUT="Yes"          TYPE="EXCLUSIVE" >     <CFSET SESSION.UserLoggedIn="True">     <CFSET SESSION.UserNanme="#qLoginQuery.UserName#">     <CFSET SESSION.UserRole="#qLoginQuery.UserRole#">  </CFLOCK>

The roles for this user would typically be stored in a database along with the user's username and password. In the preceding code, we have run a query and are assigning the UserName and UserRole values from that query to our Session variables. Whenever we come across some functionality that might be restricted, we use a simple IF statement to check the functionality against the user's role. The following code illustrates how we can accomplish this:

 <CFLOCK TIMEOUT="10"          THROWONTIMEOUT="Yes"          TYPE="READONLY"          SCOPE="SESSION">    <CFIF SESSION.UserRole IS "Administrator">        <A HREF="Delete.cfm?nid=#qNews.NewItemID#">Delete This Item</A>    </CFIF>  </CFLOCK>

This code ensures that the Delete This Item link is only displayed if the current user is an Administrator. If the current user is not an Administrator, the link will not display, and the user will have no link to follow.

If the user is familiar with the site structure, however, he would still be able to type the path to the Delete.cfm page directly into the browser and run the template. To prevent this from happening, you also could add code to the top of the Delete.cfm file that checks whether the user requesting the page is an Administrator. If he is not, we could redirect him as shown here:

 <!--- this code restricts the running of this template to        only those users who are administrators --->  <CFLOCK SCOPE="SESSION"          THROWONTIMEOUT="Yes"          TYPE="READONLY"          TIMEOUT="10">        <CFIF SESSION.UserRole NEQ "Administrator">              <CFLOCATION URL="RoleError.cfm">        </CFIF>  </CFLOCK>

This code redirects users to an error page if they try to run this template but are not an Administrator.

Other Options

Storing users' security information in the application's database is not the only option. User authentication can also be done at the operating system level. For instance, if you are running ColdFusion on a Windows 2000 server, you could restrict access to certain directories using Windows 2000 permissions and user accounts.

The drawback to this method is that it makes your application less portable. If you need to move your application from one server to another, you have to then reapply the operating system permissions to the affected folders and possibly re-create all the user accounts if you are moving to a server in another domain. In addition, if you are hosting your site with a commercial hosting provider, you might not have access to operating systemlevel security settings.

ColdFusion also supports the use of the Lightweight Directory Access Protocol (LDAP) for authentication. LDAP is an open-standard network protocol designed to provide access to structured directories of information, such as a Windows 2000 Active Directory. An LDAP directory typically contains a broad range of information about different types of network objects, including users, their passwords, and group memberships. For more information about using LDAP with ColdFusion MX, consult the Macromedia ColdFusion MX documentation available at Macromedia's web site or follow the links from www.LearnColdFusionMX.com.

By storing all user and role information in our application's database and building authentication and authorization code into our templates, we ensure that our application will be as portable as possible. With all security information as an integral part of our application code, we can bundle up our application, drop it on another server, adjust the DSN settings, and be off to the races.

New Tags and Functions

As previously mentioned, most developers have a need for authentication and authorization sooner or later. Until now, developers have been creating their own custom user security systems using the basic building blocks of ColdFusion.

Because the need for user security is so commonand because most custom user security systems consist of the same or similar elements (user IDs, roles, Session variables, and so on)Macromedia has responded by including new security-related tags and functions in the release of ColdFusion MX. Now, instead of spending valuable time creating your own custom system, you can use built-in security tags and functions to streamline your development projects.

The new tags and functions operate in a very similar fashion to the one previously outlined. ColdFusion security tags utilize user Session variables to track user logins and logouts. These new features also include the capability to assign role information to individual users, also using the Session scope. Because this functionality relies on Session scope variables to track user information, the use of the Session scope must be enabled in both ColdFusion Administrator and your Application.cfm file.

Table 9.2 outlines the new ColdFusion MX security elements and gives a brief description of their function. Each new element is discussed in greater detail in the sections that follow.

Table 9.2. New ColdFusion MX Security Elements

Element Name

Description

<CFLOGIN>

This tag is a container tag and is used to surround code that is executed at the time a user is logged in to the application. The <CFLOGIN> block must contain the <CFLOGINUSER> tag.

<CFLOGINUSER>

This tag is used within the <CFLOGIN> block and contains information about the user being logged in.

<CFLOGOUT>

This tag is used to log a user out. It is an empty tag and takes no attributes.

GetAuthUser()

This function returns the identification of the currently logged-in user.

IsUserInRole()

This function is used to determine whether a user belongs to a particular role or group.

Because these tags and functions use the Session scope, they would normally have to be locked during access using the <CFLOCK> tag. However, this functionality has been built into these tags and functions, so additional locking code is not required.

<CFLOGIN> and <CFLOGINUSER>

These two tags work together to log a user in to our application. The <CFLOGIN> tag is a container tag and must include the <CFLOGINUSER> tag, as follows:

 <CFLOGIN>     <CFLOGINUSER ...>  </CFLOGIN>

The <CFLOGINUSER> tag takes the three attributes listed in Table 9.3.

Table 9.3. <CFLOGINUSER> Attributes

Attribute

Description

NAME

Required. This attribute is the ID value for the logged-in user. It is also the value that will be returned by the GetAuthUser() function.

PASSWORD

Required. This is the user's password. It is used in combination with the username to generate a unique ID.

ROLES

Optional. This is the role(s) to which the user belongs. Multiple roles must be separated with a comma. ColdFusion will treat any spaces as significant and part of the role names, so do not put extra spaces around commas.

Right:

 ROLES="Sales,Human Resources"

Wrong:

 ROLES="Sales, Human Resources"

In addition to the <CFLOGINUSER> tag, the <CFLOGIN> block can contain any other code you would like to utilize at the time of login, as shown in the following code:

 <CFLOGIN>     <CFLOGINUSER Name="#qLogin.UserName#"                  Password="qLogin.Password"                  Roles="#qLogin.Roles#">     <!--- you can place any additional code you like here --->     <CFSET SESSION.LoginTime=Now()>  </CFLOGIN>

The preceding code logs a user in based on the values of a query and creates a SESSION.LoginTime variable to track the time at which the user logged in.

<CFLOGOUT>

The <CFLOGIN> tag uses Session scope variables to track a logged-in user's name and any roles to which that user belongs. Session scope variables normally time out after a period of inactivity, so if the user remains inactive for a period of time (specified in ColdFusion Administrator or Application.cfm), his login will time out. If he returns to his browser to continue working, he will be forced to log in again. If we want to be able to clear a particular user's login information before it naturally times out, we must manually log that user out.

We can use the <CFLOGOUT> tag to manually log a user out. The <CFLOGOUT> tag clears the user's NAME and ROLE information from the Session scope. Using the <CFLOGOUT> tag is a snapno attributes, no nothing, just the tagas follows:

 <CFLOGOUT>

It doesn't get any easier than that.

GetAuthUser()

The GetAuthUser()function returns the ID of the authenticated/logged-in user as specified in the <CFLOGINUSER> tag's NAME attribute. This function is used just like any other ColdFusion variable or function, as follows:

 <CFOUTPUT>Welcome back, #GetAuthUser()#</CFOUTPUT>

The preceding code would simply display a personalized greeting to the logged-in user.

IsUserInRole()

The IsUserInRole() function returns TRUE if the logged-in user is a member of the role specified by the function. This role information is stored in the Session scope and is set by the ROLES attribute of the <CFLOGINUSER> tag. The following example illustrates the use of the IsUserInRole() function:

 <CFIF IsUserInRole("Administrator")>    <A HREF="Delete.cfm?nid=#qNews.NewItemID#">Delete This Item</A>  </CFIF>

This code checks the logged-in user's role information to see if it contains the value Administrator. If it does, it displays the Delete This Item link.

<CFABORT>

Before we begin planning our security for the Beelze-Bubba site, we need to look at one more tag that is not necessarily security related but that will come in handy all the same. That tag is <CFABORT>. The <CFABORT> tag is similar to the <CFBREAK> tag that we saw in Step 4, "Controlling Program Flow." If you remember, the <CFBREAK> tag stops the processing of a loop and jumps outside the loop to continue with the rest of the code in the template.

The <CFABORT> tag simply halts the processing of a template. When ColdFusion Server comes across a <CFABORT> tag, it stops the processing of the template at that spot, does not pass go, does not collect $200, and just stops. Whatever has been processed up to that point is returned to the client's browser.

The <CFABORT> tag has an optional SHOWERROR attribute that can be used to display a custom error message at the point at which the template gets aborted.

User Security Flow

Before we start building user security into the administration section of our site, let's look at the flow of security. This flow is illustrated in Figure 9.1.

Figure 9.1. User security flow.

graphics/09fig01.gif

In Step 6, "Updating, Inserting, and Deleting Database Records," we created an administration section for the Beelze-Bubba site. At the moment, however, anyone can access this part of the site. We want to restrict access to the administration section to only those users who have logged in and been authenticated.

When a user requests any page in the Admin subdirectory, we would like to see whether that user is logged in. If he is not logged in, we would like to present him with the login page. After the user has logged in, we would like to check what role the user belongs to and display the tools he is authorized to use.

To accomplish this, we are going to create a login form to authenticate users and log them in and to edit some of our existing administration templates to add additional security code. Figure 9.2 illustrates the roles each template will play in our user security flow.

Figure 9.2. The Templates' Roles.

graphics/09fig02.gif

Somebody Get Me Out of This Cache

A cache is a location used to store things temporarily. Your browser uses your computer's hard drive to cache some web pages that you visit. When you hit the back button on your browser, it might retrieve the previously visited web page from the cache rather than retrieving it from the Internet again (depending on the type of file it is).

There are also special servers on the Internet known as proxy servers that cache requested web pages. For example, it is quite common for companies that provide web access to their employees to have all the employees accessing the web through a proxy server. This proxy server actually makes requests for web pages on behalf of all the employees. In addition, the proxy server usually caches the retrieved pages on its hard drive. If Employee 1 requests a page that has not been requested before, the proxy server will fetch that page, return it to the employee, and cache a copy. When Employee 2 requests the same page a little later, the proxy server checks its cache, sees that it has a local copy of the page, and returns the cached copy to Employee 2.

Usually all this caching is a good thing. It speeds up response time for the person requesting the page and eases network congestion on the Internet. However, when we start talking about secured pages, we do not want these pages stored in cache. We want them served up fresh every time. Normally, this will happen just by virtue of the fact that they end with a .cfm extension. Usually caches will not store dynamic pages types, such as .cfm, .asp, and .jsp. However, sometimes this does happen.

We can take the "better-safe-than-sorry" approach and include instructions in our code that specifically tell browsers and proxy servers not to cache our pages.

We can use HTML <META> tags to instruct client browsers not to cache pages locally on the user's hard drive. The following tags show how this is done:

[View full width]

<!--- HTML meta tags to help prevent caching ---> <META HTTP-EQUIV="Expires" CONTENT="mon, 01 jan 1990 00:00:01 graphics/ccc.gifgmt"> <META HTTP-EQUIV="Pragma" CONTENT="no-cache"> <META HTTP-EQUIV="cache-control" VALUE="no-cache, no-store, graphics/ccc.gifmust-revalidate">

These tags tell the browser that the page content has expired and should be checked again. They also instruct the browser not to cache the page at all and to revalidate the page every time it is requested.

The tags work well for browsers because the browser "reads" the <META> tags as it loads the page for display. However, as a page travels from its home server to a client, it might pass through any number of ISP and company proxy servers along the way. A proxy server does not normally "read" the HTML included in the pages that pass through it, so it would ignore the <META> tags previously mentioned. Proxy servers do, however, "read" HTTP headers that accompany each page request and response. These HTTP headers are normally invisible to end users like you and me. However, we can get our ColdFusion Server to add HTTP headers when a page is served up. This is done with the <CFHEADER> tag. The following code shows how this is done:

[View full width]

<!--- CF Tags to help prevent caching ---> <CFHEADER NAME="Expires" VALUE="mon, 01 jan 1990 00:00:01 gmt"> <CFHEADER NAME="Pragma" VALUE="no-cache"> <CFHEADER NAME="cache-control" VALUE="no-cache, no-store, graphics/ccc.gifmust-revalidate">

These tags add HTTP headers that contain information similar to our <META> tags. For more information on web caching, go to http://www.web-caching.com/.


    Team-Fly    
    Top
     



    ColdFusion MX. From Static to Dynamic in 10 Steps
    ColdFusion MX: From Static to Dynamic in 10 Steps
    ISBN: 0735712964
    EAN: 2147483647
    Year: 2002
    Pages: 140
    Authors: Barry Moore

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net