Using cflogin Properly

So, I've just been implementing cflogin on one of my web sites. With 5+ years experience in ColdFusion this may seem odd, but, in my defense, my team implemented a little more comprehensive security and authentication system which did not use cflogin.

Thus, I had a hard time finding a problem with my cflogin code, which is in my Application.cfc:

<cfset var qrylogin = "" />

   <cflogin>
      <cfif IsDefined("form.username")>
         <cfquery name="qrylogin" datasource="#application.dsn#">
            SELECT * FROM lwm_user
               WHERE username = <cfqueryparam value="#form.username#" cfsqltype="cf_sql_varchar" />
                  AND password = <cfqueryparam value="#Hash(form.password)#" cfsqltype="cf_sql_varchar" />;
         </cfquery>
         
         <cfif qrylogin.RecordCount EQ 1>
            <cfloginuser name="#form.username#" password="#form.password#" roles="#qrylogin.role_list#" />
            <cflocation url="#cgi.http_referer#" addtoken="false" />         
         </cfif>
      </cfif>
      

         <cfinclude template="/CStores/content/includes/login.cfm" />
         <cfoutput>#getSimpleFooter()#</cfoutput><cfabort>

   </cflogin>

I quickly found that this code would not work properly. I was expecting to use getAuthUser() and isUserLoggedIn() but found they contained [empty string] values.

I began to search beyond my bubble and looked into Ray Camden's Lighthouse code and found the solution:

<cfset var qrylogin = "" />
   <cfset var showLogin = true />
   
   <!--- Check to see if they are logged in. CMS --->
   <cflogin>
      <cfif IsDefined("form.username")>
         <cfquery name="qrylogin" datasource="#application.dsn#">
            SELECT * FROM lwm_user
               WHERE username = <cfqueryparam value="#form.username#" cfsqltype="cf_sql_varchar" />
                  AND password = <cfqueryparam value="#Hash(form.password)#" cfsqltype="cf_sql_varchar" />;
         </cfquery>
         
         <cfif qrylogin.RecordCount EQ 1>
            <cfloginuser name="#form.username#" password="#form.password#" roles="#qrylogin.role_list#" />
            <cfset showLogin = false />
         </cfif>
      </cfif>
      
      <cfif showLogin>
         <cfinclude template="/CStores/content/includes/login.cfm" />
         <cfoutput>#getSimpleFooter()#</cfoutput><cfabort>
      </cfif>
   </cflogin>
   
   <cfinclude template="#arguments.targetPage#">

The difference is I got rid of the cflocation after validation and added the showLogin variable to include the login form if needed. This worked perfectly. Some thoughts:

1) I'm assuming that the </cflogin> tag needs to be completely parsed in order for the login to complete. Because I relocated before the </cflogin>, nothing was happening.

2) While placing the login code and query in the Application.cfc is convenient, I'm not sure if this is the proper place for it. I guess, I could move it into a component which just makes it a little more modular. However, this location is great especially for this application where authentication is required anywhere in the system. Need to figure out a way to implement it in only certain places of the site.

3) I'm thinking we could have used this in my previous project. It's so easy to implement. But why make it easy when you can do it yourself?! Duh.

Comments
Johan's Gravatar I think it is simply that the auth cookie does not get set with the cflocation
# Posted By Johan | 8/3/08 2:48 PM
Contact Chris SchofieldBlogCFC was created by Raymond Camden. This blog is running version 5.9.001.