Solved

CF - set session variables without an Application.cfm

Posted on 2013-01-16
25
809 Views
Last Modified: 2013-01-24
I have a admin login page that I created with it's own session management.  It takes only the logins I want but after the login redirect, the admin page is not reading it as a valid session - this fails

<cfif not IsDefined('SESSION.ID')>
  <cflocation url="AdminLogin.cfm">
</cfif>  

and it keeps going back to the admin login page.  If I take out the

<cfif not IsDefined('SESSION.ID')>
  <cflocation url="AdminLogin.cfm">
</cfif>

from the page then it works but it is not restricting which means it does not see a session defined.

Can I have a separate session with the admin login page?

This is the login page

<cfapplication name="Name of application"
 sessionmanagement="yes"
 sessiontimeout="#CreateTimeSpan(0,0,20,0)#">
 
 
<cfparam name="URL.logout" default="0">
<cfparam name="invalid_login" default="0">
<!-- Define the datasource (DSN) name -->
<cfset dsource = "datasource">

<!-- Code will not be executed unless #FORM.username# IS NOT "" -->
<cfif structKeyExists(form,"email_name")>

    <!-- Check Username, Password, and Level of Administration -->
    <cfquery name="check_user" datasource="#dsource#">
            SELECT email_name, user_password
            FROM Employee_dataTest
            WHERE email_name = '#FORM.email_name#' and user_password = '#FORM.user_password#' AND access_level = 5
    </cfquery>

    <!-- If there is a valid User then Login user -->
    <cfif check_user.recordcount is not 0>
        <!-- Log them in with a timeout of 30 minutes (1800 sec) and set level of Admin-->
         <cflocation url = "admin.cfm">
    <cfelse>
        <!-- If an invalid Login Attemp, Set invalid to 1 for invalid login script -->
        <cflocation url = "login.cfm">
    </cfif>

</cfif>


<!--- Simple index.cfm file that logs you in --->
<cfif GetAuthUser() is "">
    <form name="form1" method="post" action="AdminLogin.cfm">
        Email: <input name="email_name" type="text" id="email_name"><br>
        Password: <input name="user_password" type="text" id="user_password"><br>
        <input type="submit" name="Submit" value="Submit">
    </form>
</cfif>
0
Comment
Question by:JohnMac328
  • 16
  • 9
25 Comments
 
LVL 52

Expert Comment

by:_agx_
ID: 38783437
No, you can't do it that way.  

If you don't have an Application.cfm/cfc file then the application/session variables only apply to the page with the <cfapplication> tag. Once you leave that page, you move outside the scope of that application. That's why the session variables aren't defined anymore.

For it to work, you'd have to include  "<cfapplication name="Name of application" ...> in *every* page where you're using the session variables. Which is *not* a good idea IMO.  

The simplest option is to do it the usual way ie use an Application.cfm file
0
 

Author Comment

by:JohnMac328
ID: 38783482
Makes sense - how about if I add a login form to the original like this

<CFIF ISDEFINED("Form.Submit") and form.submit eq "Log In">

  <CFIF CHECK_USER.RECORDCOUNT GT 0>
  <CFSET SESSION.LoggedIn="Yes">
  <CFSET SESSION.ID=CHECK_USER.ID>



 <cflocation url = "summary.cfm">
 <cfelse>
  <script language="JavaScript">
    alert( 'Please check your username and password, then try again.');
    self.location="login.cfm";
  </script>
 
  </cfif>
</CFIF>


New Form

<CFIF ISDEFINED("Form.Submit") and form.submit eq "Admin Log In">

  <CFIF CHECK_AdminUSER.RECORDCOUNT GT 0>
  <CFSET SESSION.LoggedIn="Yes">
  <CFSET SESSION.ID=CHECK_AdminUSER.ID>



 <cflocation url = "Admin.cfm">
 <cfelse>
  <script language="JavaScript">
    alert( 'Please check your username and password, then try again.');
    self.location="login.cfm";
  </script>
 
  </cfif>
</CFIF>
0
 

Author Comment

by:JohnMac328
ID: 38783498
And add this to application.cfm

<cfif structKeyExists(form,"Password")>
   
    <cfquery name="check_Adminuser" datasource="#datasource#">
           SELECT * FROM employee_data
 WHERE email_name = '#Form.Email#'
 AND user_password = '#Form.Password#' AND access_level = 5
    </cfquery>

</cfif>
0
 
LVL 52

Expert Comment

by:_agx_
ID: 38783600
What's the reason for having session variables in the login form? Seems like you could handle it in Application.cfm. I can't test this now, but something like this might work

<cfparam name="SESSION.LoggedIn" default="No">

<!--- handle attempted login --->
<cfif structKeyExists(form,"Password")>
    <cfquery name="check_Adminuser" datasource="#datasource#">
           .. run query to see if user is an ADMIN
    </cfquery>
     <!--- success --->
    <cfif check_AdminUser.recordCount>
           <CFSET SESSION.LoggedIn="Yes">
           <CFSET SESSION.ID=CHECK_AdminUSER.ID>
          <--- failed --->
     <cfelse>
           <CFSET SESSION.LoggedIn="No">
           <CFSET SESSION.ID = 0>
    </cfif>
</cfif>


<!--- user is NOT logged in OR the login failed. redirect to login page --->
<cfif SESSION.LoggedIn eq "no" and listLast(cgi.script_name, "/\") neq "login.cfm">
      <cflocation url = "login.cfm">
</cfif>
0
 

Author Comment

by:JohnMac328
ID: 38784328
I get Element RECORDCOUNT is undefined in CHECK_ADMINUSER.

Here is the form
<CFIF ISDEFINED("Form.Submit") and form.submit eq "Admin Log In">

<cfform name="login" method="post"  action="Adminlogin.cfm">
<table class="displayTable">
<tr>
  <td class="fundName">Email:</td><td><cfinput type="text" name="Email"></td><td></td>
</tr>
  <tr>
<td class="fundName">Password:</td><td><cfinput type="password" name="AdminPassword"><td><cfinput type="submit" name="Submit" value="Admin Log In"></td>
</td>
</tr>
 </table>
</cfform>

and this is in Application.cfm

<cfparam name="SESSION.LoggedIn" default="No">

<cfif structKeyExists(form,"AdminPassword")>
   
    <cfquery name="check_AdminUser" datasource="#datasource#">
           SELECT * FROM employee_data
 WHERE email_name = '#Form.Email#'
 AND user_password = '#Form.AdminPassword#' AND (access_level = 5)
    </cfquery>

</cfif>

<cfif check_AdminUser.recordCount>
           <CFSET SESSION.LoggedIn="Yes">
           <CFSET SESSION.ID=CHECK_AdminUSER.ID>
     <cfelse>
           <CFSET SESSION.LoggedIn="No">
           <CFSET SESSION.ID = 0>
    </cfif>



<!--- user is NOT logged in OR the login failed. redirect to login page --->
<cfif SESSION.LoggedIn eq "no" and listLast(cgi.script_name, "/\") neq "Adminlogin.cfm">
      <cflocation url = "Adminlogin.cfm">
</cfif>
0
 
LVL 52

Expert Comment

by:_agx_
ID: 38784412
>  <cfif check_AdminUser.recordCount>

Check my example again. That whole block must be nested inside the earlier CFIF

<!--- handle attempted login --->
<cfif structKeyExists(form,"Password")>
    <cfquery name="check_Adminuser" datasource="#datasource#">
           .. run query to see if user is an ADMIN
    </cfquery>
     <!--- success --->
    <cfif check_AdminUser.recordCount>
           ... set session variables indicating SUCCESS
     <cfelse>
           ... set session variables indicating FAILURE
    </cfif>

</cfif>
0
 

Author Comment

by:JohnMac328
ID: 38784545
Is there a problem with the syntax?

It won't login unless I take out the "access_level = 5" parameter

the level 5 is in the record with my login email and password

           SELECT * FROM employee_data
 WHERE email_name = '#Form.Email#'
 AND user_password = '#Form.AdminPassword#' AND (access_level = 5)

field type for access_level is an int

If I take that out the login works but not filtering
0
 
LVL 52

Expert Comment

by:_agx_
ID: 38784806
If the query runs without error, there's no syntax problems. Logic problems maybe.

Hm... do _two_ login pages? One for admins (ie access_level = 5) and another for regular users? Each with different variables?

          form.password vs form.AdminPassword
0
 

Author Comment

by:JohnMac328
ID: 38784825
That is what I am currently doing - it does not make

<cfif check_AdminUser.recordCount>

true unless I take out the access_level = 5 parameter - I must be missing something
0
 
LVL 52

Expert Comment

by:_agx_
ID: 38784918
Yeah, I understand. It would fail for anyone who *doesn't* have an access level of 5, because the query only returns users that have access_level = 5.

That's what led me to asking if you're handling 2 different logins:
 
 1) one for admins (ie  access_level = 5) ... and
 2) another for regular users ( access_level <> 5)

If it's both 1 & 2, then the current query won't work. It'll only work for admins.

What I usually do in apps with different access levels is have the query validate the email/password *only*.  Then store the access level in a session variable. In psuedo code it'd be more like this:


<cfparam name="SESSION.LoggedIn" default="No">
<cfparam name="SESSION.AccessLevel" default="0">

<!--- handle attempted login --->
<cfif structKeyExists(form,"Password")>
    <cfquery name="check_Adminuser" datasource="#datasource#">
          SELECT ID, Access_Level 
          FROM    employee_data
          WHERE  email_name = '#Form.Email#'
          AND      user_password = '#Form.AdminPassword#' 
    </cfquery>

     <!--- success --->
    <cfif check_AdminUser.recordCount>
           <CFSET SESSION.LoggedIn="Yes">
           <CFSET SESSION.ID=CHECK_AdminUSER.ID>
           <CFSET SESSION.AccessLevel = CHECK_AdminUSER.Access_Level >
          <--- failed --->
     <cfelse>
           <CFSET SESSION.LoggedIn="No">
           <CFSET SESSION.ID = 0>
           <CFSET SESSION.AccessLevel = 0>
    </cfif>
</cfif>

Open in new window


Once you've got the current user's access level, use it to determine what areas they can/can't access. Again, not tested code but should give the idea

<!--- user is NOT logged in OR the login failed. redirect to login page --->
<cfif SESSION.LoggedIn eq "no" and listLast(cgi.script_name, "/\") neq "login.cfm">
      they're not logged in at all, redirect to login
<cfelseif TryingToAccessTheAdminArea and SESSION.AccessLevel NEQ 5>
      user is logged in, but doesn't have access to admin area
      show an error or do something here.
</cfif>
0
 

Author Comment

by:JohnMac328
ID: 38787241
Here is what I did - it does not recognize my access level - it should show the admin table based on my login credentials but it gives me the "Not authorized for the area" message I setup.

<cfif structKeyExists(form,"Password")>
   
    <cfquery name="check_user" datasource="#datasource#">
           SELECT * FROM employee_data
 WHERE email_name = '#Form.Email#'
 AND user_password = '#Form.Password#'
    </cfquery>

</cfif>


<cfparam name="SESSION.LoggedIn" default="No">
<cfparam name="SESSION.AccessLevel" default="0">

<cfif structKeyExists(form,"AdminPassword")>
    <cfquery name="check_AdminUser" datasource="#datasource#">
 SELECT ID, access_level
          FROM    employee_data
          WHERE  email_name = '#Form.Email#'
          AND      user_password = '#Form.AdminPassword#' 
    </cfquery>


<cfif check_AdminUser.recordCount>
           <CFSET SESSION.LoggedIn="Yes">
           <CFSET SESSION.ID=CHECK_AdminUSER.ID>
           <CFSET SESSION.AccessLevel = CHECK_AdminUSER.Access_Level >
           <cflocation url = "http://localhost/admin.cfm">
     <cfelse>
      <cfset strError = "Error">
           <CFSET SESSION.LoggedIn="No">
           <CFSET SESSION.ID = 0>
           <CFSET SESSION.AccessLevel = 0>
    </cfif>

</cfif>

<!--- user is NOT logged in OR the login failed. redirect to login page  --->
<cfif SESSION.LoggedIn eq "no" and listLast(cgi.script_name, "/\") neq "Adminlogin.cfm">
      <cflocation url = "Adminlogin.cfm">
</cfif> 


<!--- Below is the Admin page code --->

<cfif isDefined("SESSION.LoggedIn") AND SESSION.AccessLevel EQ 5 >

Table with admin data

<cfelse>
<table><th>Not authorized for this area</th></table>
</cfif>

Open in new window

0
 
LVL 52

Expert Comment

by:_agx_
ID: 38787573
The code's using 2 different password variables which could be part of the problem.  If you're submitting #Form.AdminPassword#, the code block that checks the password will never execute, because FORM.password isn't defined.

<!--- this won't run if the form variable is called "AdminPassword" --->
<cfif structKeyExists(form,"Password")>
      ....
      AND      user_password = '#Form.AdminPassword#'
      ...
</cfif>

Also, what about my earlier question?  Are you trying to validate *only* users with access_level = 5 OR other users too? I need to know the answer before I can tell you the correct code/query to use.
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 

Author Comment

by:JohnMac328
ID: 38787625
Only users with an access level of 5 -
0
 

Author Comment

by:JohnMac328
ID: 38789344
For some reason this is hit and miss - I just put this in to filter whether the table shows or not.  I log in as different people and it is not consistent with the value of 5 that i change in the table - Sometimes it displays correctly and other times it does not

 <cfquery name="getSuper" datasource="#datasource#">
 SELECT ID, access_level
          FROM    employee_data
          WHERE     (ID = '#SESSION.ID#') AND (access_level = 5)
</cfquery>


<cfif getSuper.recordCount>

Show table

 <cfelse>
<table><th>Not authorized for this area</th></table>
</cfif>

Open in new window

0
 

Author Comment

by:JohnMac328
ID: 38789368
It lets me in every time - does not matter if I have a 5 or not in access_level

Other people (I login with their username and password) does not display the table and gives the " Not authorized for this area" even though they have a 5 in the access_level field
0
 

Author Comment

by:JohnMac328
ID: 38789380
This is the session variable

<cfif not IsDefined('SESSION.ID')>
  <cflocation url="Adminlogin.cfm">
</cfif>
0
 

Author Comment

by:JohnMac328
ID: 38789521
Ok - I took out the sessionID from this query

 <cfquery name="getSuper" datasource="#datasource#">
 SELECT ID, access_level
          FROM    employee_data
          WHERE     (ID = '#SESSION.ID#') AND (access_level = 5)
</cfquery>

And it lets everyone in - so it is not seeing the access_level parameter - I run the same query in SQL and it filters just fine.  I have never had this much trouble getting data to filter correctly
0
 

Author Comment

by:JohnMac328
ID: 38793604
I took the easy route and created an admin table for the login - if they are not in the table they can't login.  Still bugs me that a filter would not work when something very similar is in another program of mine that works.
0
 
LVL 52

Expert Comment

by:_agx_
ID: 38794083
Sorry for the lack of response, got hit with a deadline .. TGIF
0
 

Author Comment

by:JohnMac328
ID: 38794085
No problem agx - it was not a hot button issue - TGIF for sure - been one of those weeks.
0
 
LVL 52

Accepted Solution

by:
_agx_ earned 500 total points
ID: 38797733
Sure has .. so glad it's the w/e.

I tried this code with a few sample pages and it worked without a hitch. (Note, I cleared cookies each time). The "admin" user could access otherPage.cfm, but the regular "user" was redirected to the login page.  So I'm not sure what was going on in your code. I saw several versions of the login page and form fields:  ie login.cfm/form.password, AdminLogin.cfm/form.adminPassword.  Maybe that had something to do with it?

employee_data
id,  email, password, access_level
1	admin@company.com	yyy	5
2	user@company.com	xxx	0

Open in new window


Application.cfm  (with debug code)
<cfapplication name="Name of application"
	sessionmanagement="yes"
 	sessiontimeout="#CreateTimeSpan(0,0,20,0)#">

<cfset datasource = "Some DSN Here">

<cfparam name="SESSION.LoggedIn" default="No">
<cfparam name="SESSION.AccessLevel" default="0">

<cfif structKeyExists(form, "Password")>
   ::DEBUG:: Validating password <br>
    <cfquery name="check_user" datasource="#datasource#">
           SELECT  ID, Access_Level
		   FROM    employee_data
           WHERE   email_name = <cfqueryparam value="#Form.Email#" cfsqltype="cf_sql_varchar">
		   AND     user_password = <cfqueryparam value="#Form.Password#" cfsqltype="cf_sql_varchar">
		   AND     access_level = 5
    </cfquery>

   ::DEBUG:: Records found: <cfoutput>#check_user.recordCount#</cfoutput> <br>

	<cfif check_user.recordCount>
        <CFSET SESSION.LoggedIn = "Yes">
        <CFSET SESSION.ID = check_user.ID>
        <CFSET SESSION.AccessLevel = check_user.Access_Level >
   		::DEBUG:: Admin found. Initialized Settings<br>
    <cfelse>
        <CFSET SESSION.LoggedIn="No">
        <CFSET SESSION.ID = 0>
        <CFSET SESSION.AccessLevel = 0>
   		::DEBUG:: ERROR. Admin not found<br>
    </cfif>
</cfif>

<!--- user is NOT logged in OR the login failed. redirect to login page --->
<cfif SESSION.LoggedIn eq "no" and listLast(cgi.script_name, "/\") neq "login.cfm">
	<cflocation url="login.cfm?message=Not logged in or login failed">
</cfif> 

Open in new window


Login.cfm
    <cfparam name="url.message" default="">
    <div><cfoutput>#url.message#</cfoutput></div>
    <form name="form1" method="post" action="otherPage.cfm">
        Email: <input name="email" type="text" value="user@company.com"><br>
        Password: <input name="password" type="text" value="yyy"><br>
        <input type="submit" name="Submit" value="Submit">
    </form>

Open in new window


OtherPage.cfm
<h1>Other (Admin) page</h1>
Time now <cfoutput>#now()#</cfoutput>
0
 

Author Comment

by:JohnMac328
ID: 38806582
I will test this out and let you know the results - thanks!
0
 

Author Closing Comment

by:JohnMac328
ID: 38814674
That worked fine.  Now I will compare to what I had going to see what the difference was.

Thanks!
0
 
LVL 52

Expert Comment

by:_agx_
ID: 38815128
Great, at least we finally found something that works :)
0
 

Author Comment

by:JohnMac328
ID: 38815785
So true :)
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Load balancing is the method of dividing the total amount of work performed by one computer between two or more computers. Its aim is to get more work done in the same amount of time, ensuring that all the users get served faster.
This article describes how to create custom column layout styles for Bootstrap. The article uses 5 columns to illustrate the concept, but the principle can be extended to any number of columns.
Via a live example, show how to setup several different housekeeping processes for a SQL Server.
Using examples as well as descriptions, and references to Books Online, show the documentation available for datatypes, explain the available data types and show how data can be passed into and out of variables.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now