24 Replies Latest reply on Jan 27, 2010 9:26 AM by TiGGi

    user struct in session

    TiGGi

      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>

        • 1. Re: user struct in session
          BKBK Adobe Community Professional & MVP

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

          • 2. Re: user struct in session
            -==cfSearching==- Level 4

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

            • 3. Re: user struct in session
              TiGGi Level 1

              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.

              • 4. Re: user struct in session
                BKBK Adobe Community Professional & MVP
                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.

                • 5. Re: user struct in session
                  TiGGi Level 1

                  I already did, I moved  onApplicationStart from the root application.cfc to this one and removed cfinclude.  I am still getting same problem.  Thanks

                  • 6. Re: user struct in session
                    BKBK Adobe Community Professional & MVP

                    Ok, now it's time for us to solve the problem. I wish to understand how the session-not-found occurs.

                     

                    Suppose the session has timed out. Do you get session-not-found after you successfully log in, and then go to a page where the session scope is dumped?

                    • 7. Re: user struct in session
                      TiGGi Level 1

                      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.

                      • 8. Re: user struct in session
                        Joshua Cyr Level 3

                        I don't use cflogin (I prefer my own systems) so I may miss something obvious that has to do with the cflogin functionality but your code at a glance has the right logic.  We still haven't seen the actual error and details (such as all the files called in order to get to it).  Or the included application.cfc.  My bet at this point is it is something in the included application.cfc.  Something is created which causes it to skip the step of either actually logging in or creating the session.user vars.  Perhaps some logic that looks for a var and assumes if it exists then the rest must also be there?

                        • 9. Re: user struct in session
                          Joshua Cyr Level 3

                          Also another thought.  Since the application.cfc is only called within the secure folder (or so I understand) maybe when they are timed out they go to the parent root and its application.cfc and thus skip the logic in your sub application.cfc?

                          • 10. Re: user struct in session
                            BKBK Adobe Community Professional & MVP

                            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]

                            • 11. Re: user struct in session
                              BKBK Adobe Community Professional & MVP

                              In my opinion,  <cfset SESSION.User = StructNew() /> belongs to onSessionStart.

                              • 12. Re: user struct in session
                                TiGGi Level 1

                                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.

                                • 13. Re: user struct in session
                                  BKBK Adobe Community Professional & MVP
                                  I got my session timeout on 10 seconds.

                                  Too small, I think. At least give Coldfusion time to breathe. Two minutes, perhaps? It needs time to clear and restart sessions, load settings, and so on.

                                   

                                   

                                  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 guess so, too.

                                   

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

                                  Still, I would leave it there, as that's the proper place for it to be. You should keep the code to clear the session in onSessionEnd as discussed above

                                   

                                  Take the suggestion from -==cfSearching==- and delete the following block. It may have helped you debug, but serves no further purpose.

                                   

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

                                   

                                  However, I believe you had the right intention. I think the following would be better placed in onSessionStart:

                                   

                                  <cfset SESSION.User = StructNew()>
                                  <cfparam name="SESSION.User.news" default="0">
                                  <cfparam name="SESSION.User.calendar" default="0">
                                  <cfparam name="SESSION.User.account" default="0">
                                  <cfparam name="SESSION.User.site" default="0">
                                  <cfparam name="SESSION.User.marketing" default="0">
                                  <cfparam name="SESSION.User.users" default="0">

                                   

                                  Add the following among the component's fields:

                                   

                                  <cfset this.applicationTimeout = createTimeSpan( 1, 0, 0, 0)>

                                   

                                  Now comes what I hope will be the breakthrough (assuming that the problem persists). Sessions are bound to the application name, which in turn is stored in the application scope until either the application times out or the server shuts down. It just could be that the application hangs on to old session settings after the session times out.  To verify this, restart Coldfusion. Less drastic alternatives are to change the application name.or to call the method onApplicationStart().

                                  • 14. Re: user struct in session
                                    TiGGi Level 1

                                    BKBK, thanks alot.

                                     

                                    I have already tried all those things and the problem persists. I even cloned the whole site on another server and I am getting the same results.  I was just trying to eliminate possibility of bad CF installation or something.

                                     

                                    I've been talking to Ban Nadel regarding this problem and he thinks that <cflogin> hangs around bit longer after the session expires which makes alot of sense to me.  That would explain how I am seeing getAuthUser() but it doesn't go through login process under the OnRequestStart.  Since user has not loged out according to CF it just skips funtions in onRequestStart.  That seams to me like a bug in the system.  Is there a better solution for login other then the <cflogin>?

                                     

                                    What do you think?

                                    • 15. Re: user struct in session
                                      BKBK Adobe Community Professional & MVP

                                      i thought of that, too. But I felt it was unlikely for that to happen in such a much-used, front-line tag.

                                       

                                      I'll post my alternative in a moment. Before that, I have two questions. What is the exact statement of the error message, and on what line does it occur?

                                      • 16. Re: user struct in session
                                        BKBK Adobe Community Professional & MVP

                                        The following code sets the user's session  variables out of the cflogin tag. However, cflogin still exercises influence on the session variables, via getAuthUser(). Also, I cached the query in session scope.If this, too, fails, then check simple things like the spelling of variable names!

                                         

                                        <cffunction name="onSessionStart">
                                            <cfset SESSION.User = structNew()>
                                            <cfparam name="SESSION.User.news" default="0">
                                            <cfparam name="SESSION.User.calendar" default="0">
                                            <cfparam name="SESSION.User.account" default="0">
                                            <cfparam name="SESSION.User.site" default="0">
                                            <cfparam name="SESSION.User.marketing" default="0">
                                            <cfparam name="SESSION.User.users" default="0">
                                        </cffunction>

                                         

                                        <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="session.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#">               
                                                    <cfelse>
                                                        <H2>Your login information is not valid.<br>
                                                        Please Try again</H2>
                                                        <cfinclude template="loginform.cfm">
                                                        <cfabort>
                                                    </cfif>
                                                </cfif>
                                            </cfif>
                                            </cflogin>
                                            <cfif getAuthUser() is not ""><!--- authenticated user exists --->
                                                <cfset SESSION.User.news =  session.loginQuery.news>
                                                <cfset SESSION.User.calendar =  session.loginQuery.calendar>
                                                <cfset SESSION.User.account =  session.loginQuery.account>
                                                <cfset SESSION.User.marketing =  session.loginQuery.marketing>
                                                <cfset SESSION.User.site =  session.loginQuery.site>
                                                <cfset SESSION.User.users =  session.loginQuery.users>
                                            </cfif>
                                        </cffunction>

                                        • 17. Re: user struct in session
                                          TiGGi Level 1

                                          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

                                          • 18. Re: user struct in session
                                            BKBK Adobe Community Professional & MVP

                                            I do believe it's OK to do it like that, even in the absence of problems!

                                            • 19. Re: user struct in session
                                              BKBK Adobe Community Professional & MVP

                                              Could you post an exact statement of the error message, and the line on which it occurs?

                                              • 20. Re: user struct in session
                                                BKBK Adobe Community Professional & MVP

                                                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.

                                                • 21. Re: user struct in session
                                                  TiGGi Level 1

                                                  I think you got it.  I've placed the timeout and so far I have not seen any errors.  Thank you very much for your help.  I like this solution much better.

                                                  • 22. Re: user struct in session
                                                    BKBK Adobe Community Professional & MVP
                                                    I think you got it.  I've placed the timeout and so far I have not seen any errors.


                                                    Yesss! I am writing to Adobe's Coldfusion team to update the documentation to include a note about the effect of not synchronizing the combined function loginStorage(in session) - sessionTimeout - cflogin.

                                                     

                                                    Every cloud has a silver lining, they say. You and I wouldn't forget that one in a hurry, would we?

                                                     

                                                    I bet it's plain sailing for you from now on. Good luck.

                                                    • 23. Re: user struct in session
                                                      BKBK Adobe Community Professional & MVP
                                                      I am writing to Adobe's Coldfusion team to update the documentation to include a note about the effect of not synchronizing the combined function loginStorage(in session) - sessionTimeout - cflogin.

                                                      Done.

                                                      • 24. Re: user struct in session
                                                        TiGGi Level 1

                                                        Good idea, I am sure there will be others that will run into this issue.  Maybe there is a reason this has been done this way but to me it would make more sense if the cflogin expires on session end.  Anyway, another possibility is to add <cflogout> to OnSessionEnd.  I haven't tried it but I think it would work.

                                                         

                                                        Thanks for all your help BKBK and Ben Nadel!!!

                                                         

                                                        Cheers