Skip to main content
Inspiring
January 19, 2010
Answered

user struct in session

  • January 19, 2010
  • 3 replies
  • 3085 views

Hi,

As part of the user login I am creating session.user variables when user logs in.  It works just fine when user logs in first time or if user logs out and logs back in.  The problem is when the session times out due to timeout setting and user tryies to log back in.  This is when session.user.* no founds error comes out.  I dump the session varables and user settings are nowhere to be found.  Why would user login be any different on time out then after logout?

here is my application.cfc

<cfcomponent>
<cfparam name="loginQuery.news" default="0">
<cfparam name="loginQuery.calendar" default="0">
<cfparam name="loginQuery.account" default="0">
<cfparam name="loginQuery.site" default="0">
<cfparam name="loginQuery.marketing" default="0">
<cfparam name="loginQuery.users" default="0">
<cfinclude template="/Application.cfc">

<cfset This.name = "Login">
<cfset This.Sessionmanagement="True">
<cfset This.clientManagement = "true">
<cfset This.loginstorage = "session">
<cfset THIS.SessionTimeout = CreateTimeSpan( 0, 0, 10, 0) />

<cffunction name="OnRequestStart" >
  <cfargument name = "request" required="true"/>
  <cfif IsDefined("URL.logout")>
    <cflogout>
    <cflocation url="/index.cfm" addtoken="no">
  </cfif>
  <cflogin>
  <cfif NOT IsDefined("cflogin")>
    <cfinclude template="loginform.cfm">
    <cfabort>
    <cfelse>
    <cfif cflogin.name IS "" OR cflogin.password IS "">
      <cfoutput>
        <h2>You must enter text in both the User Name and Password fields.</h2>
      </cfoutput>
      <cfinclude template="loginform.cfm">
      <cfabort>
      <cfelse>
      <cfquery name="loginQuery" dataSource="#Application.DNS#">
            SELECT UserID, UserLevel, news, calendar, site, marketing, account, users
            FROM Users
            WHERE
               UserID = '#cflogin.name#'
               AND Password = '#cflogin.password#'
            </cfquery>
      <cfif loginQuery.UserLevel NEQ "">
     
     
        <cfloginuser name="#cflogin.name#" Password = "#cflogin.password#" roles="#loginQuery.UserLevel#">
        <cfset SESSION.User = StructNew() />
        <cfset SESSION.User.news =  loginQuery.news/>
        <cfset SESSION.User.calendar =  loginQuery.calendar/>
        <cfset SESSION.User.account =  loginQuery.account/>
        <cfset SESSION.User.marketing =  loginQuery.marketing/>
        <cfset SESSION.User.site =  loginQuery.site/>
        <cfset SESSION.User.users =  loginQuery.users/>
       
     
        <cfelse>
        <cfoutput>
          <H2>Your login information is not valid.<br>
            Please Try again</H2>
        </cfoutput>
        <cfinclude template="loginform.cfm">
        <cfabort>
      </cfif>
    </cfif>
  </cfif>
  </cflogin>
</cffunction>
<cffunction name="onSessionEnd">
  <cfset StructClear(Session)>
  <cflocation url="/index.cfm" addtoken="no">
</cffunction>
</cfcomponent>

This topic has been closed for replies.
Correct answer BKBK

I was getting same thing, I think the problem is that the loginQuery does not run since the cflogin has not cleared.

Something like this can work but didn't really wanted to go that way:

<cfif getAuthUser() is not ""><!--- authenticated user exists --->
    <cfquery name="getUser" dataSource="#Application.DNS#">
            SELECT UserID, UserLevel, news, calendar, site, marketing, account, users
            FROM Users
            WHERE UserID = '#getAuthUser()#'
            </cfquery>
        <cfset SESSION.User.news =  getUser.news>
        <cfset SESSION.User.calendar =  getUser.calendar>
        <cfset SESSION.User.account =  getUser.account>
        <cfset SESSION.User.marketing =  getUser.marketing>
        <cfset SESSION.User.site =  getUser.site>
        <cfset SESSION.User.users =  getUser.users>
    </cfif>

thanks


I think I've got it: time cflogin out!

<cflogin idleTimeout="600">

I have chosen 600 seconds because it corresponds to the sessiontimeout value of 10 minutes. If you don't state the idletimeout attribute, Coldfusion uses the default value of 1800, which is 30 minutes! Your sessions time out much earlier than that.

3 replies

TiGGiAuthor
Inspiring
January 21, 2010

Yes I get "User.xyz is undefined in Session" after sucessfull login.  And this only happens when loging in after session expires.  If I invoke the cflogout and log back in again it works just great.  I am using session.user.xyz in the site navigation to hide/show certain menu links.

BKBK
Community Expert
Community Expert
January 21, 2010

Put the following line just before the first place where you attempt to write a session variable (the error message should have told you where that is):

<cfoutput>#getAuthUser()#</cfoutput>

Do you get a non-empty string?

[added: I would, for test purposes, reduce the sessiontimeout to just several minutes]

TiGGiAuthor
Inspiring
January 21, 2010

I've placed getAuthUser() on the index page that gets displayed after the successfull login and I am getting the user name that has loged in.  This happens when session.user errors out and when it doesn't.  So I guess it goes fine through the login process.

I've also placed the session user struct creation on onSessionStart

I am still getting user.xyz undefined error

I got my session timeout on 10 seconds.

Inspiring
January 21, 2010

<cffunction name="onSessionEnd">

<cfset StructClear(Session)>

<cflocation url="/index.cfm" addtoken="no">

</cffunction>

Also, onSessionEnd is not associated with a request. So the cflocation probably will not do anything.

<cfparam name="loginQuery.news" default="0">

<cfparam name="loginQuery.calendar" default="0">

Why cfparam a query used in OnRequestStart?

TiGGiAuthor
Inspiring
January 21, 2010

Thanks for the reply...

My original OnSessionEnd is blank, I was just trying things to see if would help.  I proly do not even need onSessionEnd.

As far as including root application.cfc, that one has all the application settings that are used throughtout the site and then this application.cfc is for the secure folder only.  Session or user settings are not needed for the rest of the site.  It possible that it's bad way of doing it but it works.  I'll look into this bit more later on.  My problem still exists where loging in after session expires the session.users struct does not get created.  I just can't figure out why at all.

BKBK
Community Expert
Community Expert
January 21, 2010
It possible that it's bad way of doing it but it works.

I wouldn't say that, given that you've just reported a problem. I would use the extends attribute instead of the cfinclude tag, if only to eliminate that as the cause.

BKBK
Community Expert
Community Expert
January 21, 2010

Two things:

1) You cannot access the session scope directly in onSessionEnd. Coldfusion therefore does you a favour by passing it as an argument. Instead of

<cffunction name="onSessionEnd">
  <cfset StructClear(Session)>
</cffunction>

do this

<cffunction name="onSessionEnd">
    <cfargument name = "SessionScope" required="true">
    <cfargument name = "AppScope" required="true">
        <cfset StructClear(arguments.SessionScope)>
</cffunction>


2) It looks awkward to include one Application.cfc in another like this: <cfinclude template="/Application.cfc">. It might even be wrong.

You have to let the current Application.cfc inherit from the other. To do so, use the current CFC's extends attribute

<cfcomponent extends="dotted_path_to_parent_Application_file">