[Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 398
  • Last Modified:

Help with securing certain pages in coldfusion

I'm trying to use a new method (for me) for securing certain pages on my site safely. This approach is working but if the user starts out on the LoginForm.cfm page and not another page on the site it ends up looping them back to the form page even though the session variable has been set (user logged in). I know this is due to the cgi.script_name.... code. but how would I add additional code that if a page is not referred that it sends the user to a default location. I hope that makes sense. Please see code attached.

Question:  How would I add additional code, if a page is not referred, that it sends the user to a default location. I hope that makes sense. Please see code attached. In addition, does anyone see any fault from a security or usability standpoint on using this set up?

Thanks in advanced...this one has sent my head into a loop of no return :)
///////LOCATED AT THE TOP OF ANY PAGE I WANT TO SECURE/////
    <!--- If user isn't logged in, force them to now ---> 
    <cfif not isDefined("session.auth.isLoggedIn") OR #session.auth.isLoggedIn# is "No" >
      <!--- If the user is now submitting "Login" form, --->
      <!--- Include "Login Check" code to validate user --->
      <cfif isDefined("form.UserLogin")> 
        <cfinclude template="loginCheck.cfm">
      </cfif>
       <cfinclude template="LoginForm.cfm"> 
      <cfabort>
    </cfif> 

////////LoginForm.cfm//////////////////
<!--- If the user is now submitting "Login" form, --->
<!--- Include "Login Check" code to validate user --->
<cfif isDefined("form.UserLogin")> 
 <cfinclude template="LoginCheck.cfm">
</cfif>



<html>
<head>
 <title>Please Log In</title>
</head>

<!--- Place cursor in "User Name" field when page loads--->
<body onLoad="document.LoginForm.userLogin.focus();">

<!--- Start our Login Form --->
<cfform action="#cgi.script_name#?#cgi.query_string#" name="LoginForm" method="post">
 <!--- Use an HTML table for simple formatting --->
 <table border="0">
 <tr><th colspan="2" bgcolor="silver">Please Log In</th></tr>
 <tr>
 <th>Username:</th>
 <td>
 
 <!--- Text field for "User Name" ---> 
 <cfinput 
 type="text"
 name="userLogin"
 size="20"
 value=""
 maxlength="100"
 required="Yes"
 message="Please type your Username first.">

 </td>
 </tr><tr>
 <th>Password:</th>
 <td>
 
 <!--- Text field for Password ---> 
 <cfinput 
 type="password"
 name="userPassword"
 size="12"
 value=""
 maxlength="100"
 required="Yes"
 message="Please type your Password first.">

 <!--- Submit Button that reads "Enter" ---> 
 <input type="Submit" value="Enter">
 
 </td>
 </tr>
 </table>
 
</cfform>

</body>
</html>

///////////////////LoginCheck.cfm//////////////////
<!--- Make sure we have Login name and Password --->
<cfparam name="form.userLogin" type="string">
<cfparam name="form.userPassword" type="string">

<!--- Find record with this Username/Password --->
<!--- If no rows returned, password not valid --->
<cfquery name="getUser" datasource="#application.datasource#">
 SELECT ContactID, FirstName
 FROM contacts
 WHERE EmailAddress = 
 <cfqueryparam cfsqltype="cf_sql_varchar" value="#form.UserLogin#">
 AND Password = 
 <cfqueryparam cfsqltype="cf_sql_varchar" value="#form.UserPassword#">
</cfquery>

<!--- If the username and password are correct --->
<cfif getUser.recordCount eq 1>
 <!--- Remember user's logged-in status, plus --->
 <!--- ContactID and First Name, in structure --->
 <cfset SESSION.auth = structNew()>
 <cfset SESSION.auth.isLoggedIn = "Yes">
 <cfset SESSION.auth.contactID = getUser.contactID>
 <cfset SESSION.auth.firstName = getUser.firstName>

 <!--- Now that user is logged in, send them --->
 <!--- to whatever page makes sense to start --->
 <cflocation url="#cgi.script_name#?#cgi.query_string#">
</cfif>

Open in new window

0
jasch2244
Asked:
jasch2244
  • 11
  • 10
3 Solutions
 
gdemariaCommented:
Check the login before testing to see if the user is logged in.    That way, if the login attempt fails, you will be directed to your login page again.  If the login attempt is successful, you can move on to the next page...

Put this code in your application.cfc/.cfm page so you don't have to reproduce it.

  <!--- user is attempting to login, check credentials and log him in ----->
  <cfif isDefined("form.UserLogin")>
      <cfinclude template="loginCheck.cfm">
  </cfif>
  <!--- If user isn't logged in, force them to now --->
  <cfif not isDefined("session.auth.isLoggedIn") OR #session.auth.isLoggedIn# is "No" >
     <cfinclude template="LoginForm.cfm">
     <cfabort>
  </cfif>


> This approach is working but if the user starts out on the LoginForm.cfm page

There is no "login page" for the user to start on.   When the user goes to the site, send him to the home page (or wherever) if he's not logged in the login screen will be cfincluded but the URL will not change, the url will still be /myhome.cfm (or whatever).

When the user submits the form and it is sucessful, he will be able to see the same page /myhome.cfm - so you actually never send the user to loginForm.cfm .. .it is just cfincluded as part of any page that requires login

0
 
jasch2244Author Commented:
I understand what you are saying but I don't want to lock down the whole site only specific pages. Currently my set up is just what you are mentioning but I want the option to start on LoginForm.cfm or a page that is locked down with the code at the top. Make sense?
0
 
gdemariaCommented:

There are ways to still centralize your code and pick and choose which pages to lock down.

Typically, secure pages come in groups... you may have a folder /admin or /members that would be secure or perhaps a group of file names such as profileEdit, profileAddress, profileCreditCard... or maybe just a list of specific pages...

In your application.cfm/.cfc file simply check to see if the page being accessed in on the list or in the area.   This gives you the added benefit of centralizing your control of secure pages...


<cfif  cgi.script_name contains "/admin" or  cgi.script_name contains "profile">
    <!---- secure page code ----->

</cfif>

0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
jasch2244Author Commented:
Great suggestion.. my only issue now is by using your code I can'tt create the proper paths to the loginCheck.cfm or  LoginForm.cfm pages as all the pages I have under my Pofile folder will have different sub folders etc.
0
 
gdemariaCommented:
the path to your loginForm should be relative to the application.cfm file.  You should have one loginForm.cfm, you can place it at your root or you could create a folder /shared or /global or /app or something where you put common used files.

Then in your application.cfm file you simply reference that location...

<cfinclude template="/shared/loginForm.cfm">
<cfabort>

Same thing with loginCheck.cfm...    although for check I would consider puttting the code right into the application.cfm page (assuming it's short) or creating a function for it... but either way..
0
 
jasch2244Author Commented:
When my secured pages load the page name is in the url... not the LoginForm.cfm page. With that said the css properties are not pulling in properly as the url is showing whatever page name the security code is trying to secure. So, testpage.cfm is showing testpage.cfm in the url but the LoginForm.cfm page is displaying. I hope that makes sense.

Also, my login form and LoginCheck.cfm are all in the root with my application.cfc.

Any other thougts... should I use GetDirectoryFromPath or something?
0
 
gdemariaCommented:
> When my secured pages load the page name is in the url... not the LoginForm.cfm page.

That's good.

> With that said the css properties are not pulling in properly as the url is showing whatever page name the security code is trying to secure

How are your css files linked in?   Where are they called from?   Can you provide a bit more information on this.

> Also, my login form and LoginCheck.cfm are all in the root with my application.cfc.

That works..

> Any other thougts... should I use GetDirectoryFromPath or something?

To solve which problem?   The problem with the css files?  

0
 
jasch2244Author Commented:
gdemaria: Thank you again for all of your help past and present I always appreciate it.

I have two problems with this current set up:
1. The css issue when the LoginForm.cfm file gets called up with a different page name in the url

2. With the code <cfif not isDefined("session.auth.isLoggedIn") OR #session.auth.isLoggedIn# is "No" > if the page first loads and no session variable is defined I get an error "Element AUTH.ISLOGGEDIN is undefined in SESSION" even though in the logout.cfm page I use the code attached.
<cfset SESSION.auth.isLoggedIn="No">
    <cfset SESSION.auth.contactID="">
    <cfset SESSION.auth.firstName="">

Open in new window

0
 
gdemariaCommented:
Since you are using application.cfc, in your onSessionStart function, you should predefine your session variables so they all ways exists with default settings.

   <cfset SESSION.auth.isLoggedIn="No">
   <cfset SESSION.auth.contactID="">
   <cfset SESSION.auth.firstName="">

Once you do this... in order to test, you may have to (a) completely close and re-open a browser (b) change the name of your application at the top of your application.cfc file OR (c) restart coldfusion if you're in a dev enviroment.   This is because for your current browser session, you alredy have a session so onSessionStart will not fire.   Hopefully, just doing (a) will handle it.



> 1. The css issue when the LoginForm.cfm file gets called up with a different page name in the url

As mentioned above, this problem is not clear to me.   Why does it matter what page name is showing in the URL and how does that effect the loading of a css file?    How is the css file loaded now?





0
 
jasch2244Author Commented:
I have it under the <cffunction name="onRequestStart" access="public" returntype="void"> is that a problem?
0
 
gdemariaCommented:
> I have it under the

what is "it" ?

You can't have this under onRequstStart as it will reset your login every time...

   <cfset SESSION.auth.isLoggedIn="No">
   <cfset SESSION.auth.contactID="">
   <cfset SESSION.auth.firstName="">


But, yes,  you should have this under onRequestStart...


  <cfif isDefined("form.UserLogin")>
      <cfinclude template="/loginCheck.cfm">
  </cfif>
  <cfif not isDefined("session.auth.isLoggedIn") OR session.auth.isLoggedIn is "No" >
     <cfinclude template="/LoginForm.cfm">
     <cfabort>
  </cfif>
0
 
jasch2244Author Commented:
Sorry here is what I have thus far see code
<cfcomponent>
	<cfset this.applicationname="mysite">
    <cfset this.sessionmanagement="Yes">
    <cffunction name="onRequestStart" access="public" returntype="void">
		<cfset application.datasource="#######">
        <cfset SESSION.auth = structNew()>
        <cfset SESSION.auth.isLoggedIn = "No">
        <cfset SESSION.auth.contactID = "">
        <cfset SESSION.auth.firstName = "">
      <cfif  cgi.script_name contains "/MGMT">
		<!--- user is attempting to login, check credentials and log him in ----->
        <cfif isDefined("form.UserLogin")>
        <cfinclude template="loginCheck.cfm">
        </cfif>
        <!--- If user isn't logged in, force them to now --->
        <cfif not isDefined("session.auth.isLoggedIn") OR #session.auth.isLoggedIn# is "No" >
        <cfinclude template="LoginForm.cfm">
        <cfabort>
        </cfif> 
      </cfif>
    </cffunction>
</cfcomponent>

Open in new window

0
 
gdemariaCommented:
You should have the other functions, more like this.

Also note that I changed the app variable name from this.applicationname to this.name


<cfcomponent>
	
  <cfset this.name="mysite">
  <cfset this.applicationTimeout = createTimeSpan(0,4,0,0)>
  <cfset this.sessionManagement = true>
  <cfset this.sessionTimeout    = createTimeSpan(0,0,90,0)>
  <cfset this.setClientCookies  = true>

 <cffunction name="onApplicationStart" returnType="boolean">
	<cfset application.datasource="#######">
 </cffunction>

 <cffunction name="onSessionStart" returnType="void">
     <cfset SESSION.auth = structNew()>
     <cfset SESSION.auth.isLoggedIn = "No">
     <cfset SESSION.auth.contactID = "">
     <cfset SESSION.auth.firstName = "">
 </cffunction>

 <cffunction name="onRequestStart" access="public" returntype="void">

     <cfif cgi.script_name contains "/MGMT"> <!---- login is required for this section ---->
        <cfif isDefined("form.UserLogin")> <!--- user is attempting to login, check credentials and log him in ----->
            <cfinclude template="loginCheck.cfm">
        </cfif>
        <!--- If user isn't logged in, force them to now --->
        <cfif not isDefined("session.auth.isLoggedIn") OR session.auth.isLoggedIn is not "Yes">
           <cfinclude template="LoginForm.cfm">
           <cfabort>
        </cfif> 
      </cfif>

  </cffunction>

</cfcomponent>

Open in new window

0
 
jasch2244Author Commented:
Wow thank you I was wondering how I was going to time thinks out.. you are the best.

I'm getting: error " The value returned from the onApplicationStart function is not of type boolean"  though
0
 
gdemariaCommented:
Sorry, I accidently deleted the last line of that function...

It should be ...

 <cffunction name="onApplicationStart" returnType="boolean">
      <cfset application.datasource="#######">
      <cfreturn true>
 </cffunction>

0
 
jasch2244Author Commented:
That is awesome! Thank you so much. I'm going to open up another question regarding the css issue as you deserve more points for that issue alone.

In addition, the only problem I see with our (your) code is if I hit the back button (after a log out) the browser it still shows the page even though I have logged out. I can't navigate to any more pages but I can still see the page I was on prior to the log out.
0
 
jasch2244Author Commented:
I think I figured out the css issue... I found some old code for determining the root and paths and such. What do you think of the attached code? I basically put the #assumedRoot# variable in front of the file and coldfusion does the rest.
<cfset WA_localRoot = "/######/" >
<cfset WA_remoteRoot = "/" >
<cfset WA_curURL = IIf(isDefined("CGI.SCRIPT_NAME"),"CGI.SCRIPT_NAME",DE("")) >
<cfset assumedRoot = WA_remoteRoot>
<cfif (findnocase(WA_localRoot,WA_curURL) EQ 1 AND (Len(WA_localRoot) GTE Len(WA_remoteRoot) OR findnocase(WA_remoteRoot,WA_curURL) EQ 0))>
  <cfset assumedRoot = WA_localRoot>
</cfif>

Open in new window

0
 
gdemariaCommented:
Could you please add the call to the css file with the code you posted so I can see the whole thing?

thanks,

0
 
jasch2244Author Commented:
So code I mentioned above in the head of the document (LoginForm.cfm) and the reference to the css file like so: <link href="<cfoutput>#assumedRoot#</cfoutput>CSS/subPage.css" rel="stylesheet" type="text/css" />
0
 
gdemariaCommented:

I don't know where your subpage.css file is located, but let's say it in a folder c:/inetpub/wwwroot/css/

If so, all you would need to do is this...  a relative path starting at the root.. no variables required

<link href="/css/subPage.css" rel="stylesheet" type="text/css" />
0
 
jasch2244Author Commented:
Thank you very very much!
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 11
  • 10
Tackle projects and never again get stuck behind a technical roadblock.
Join Now