Link to home
Start Free TrialLog in
Avatar of jasch2244
jasch2244

asked on

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

ASKER CERTIFIED SOLUTION
Avatar of gdemaria
gdemaria
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of jasch2244
jasch2244

ASKER

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?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.
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..
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?
> 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?  

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

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?





I have it under the <cffunction name="onRequestStart" access="public" returntype="void"> is that a problem?
> 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>
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

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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
Sorry, I accidently deleted the last line of that function...

It should be ...

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

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.
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

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

thanks,

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" />

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" />
Thank you very very much!