Copy link to clipboard
Copied
Hi,
Since migrating from CFMX7 to CF11 we are experiencing some weird failure with cflogin (using session or cookie storage).
Basically when we log-in on the application after a session/client timeout the first login doesn't last for longer than the login submit request.
The second login however is OK
I made a very simple application.cfc/index.cfm with short timeouts to check this:
<cfcomponent
output="false"
hint="I define the application settings and event handlers.">
<!--- Define the application settings. --->
<cfset this.name = hash( getCurrentTemplatePath() ) />
<cfset this.applicationTimeout = createTimeSpan( 0, 0, 10, 0 ) />
<cfset this.sessionTimeout = createTimeSpan( 0, 0, 0, 10 ) />
<!--- Set up the application. --->
<cfset THIS.SessionManagement = true />
<cfset THIS.ClientManagement = true />
<cfset THIS.SetClientCookies = true />
<cfset THIS.loginStorage = "Session" />
<cfset THIS.clientStorage = "sidys" />
<!--- Define the request settings. --->
<cfsetting showdebugoutput="false" />
<cffunction
name="OnRequestStart"
access="public"
returntype="boolean"
output="true"
hint="Fires at first part of page processing.">
<!--- Define arguments. --->
<cfargument
name="TargetPage"
type="string"
required="true"
/>
<cfset SetLocale("fr_FR") />
<cfif IsDefined("Form.logout") or IsDefined("URL.logout")>
<cflogout />
</cfif>
<cflogin idletimeout="20">
<cfdump var="#Session#">
<cfinclude template="form.inc" />
<cfif not isDefined("cflogin") or (cflogin.name IS "" OR cflogin.password IS "")>
<cfoutput>
<form method="post">
<b>login :</b>
<input type="text" name="j_username" size="24" class="champ" />
<b>passwordnbsp;:</b>
<input type="password" name="j_password" size="15" class="champ" />
<input type="submit" value="Login" class="button" name="submit" />
</form>
</cfoutput>
<cfabort>
<cfelse>
<cflock timeout="10" scope="Session" type="exclusive">
<cfloginuser name="#cflogin.name#" Password="#cflogin.password#" roles="role">
<cfset Session.id=cflogin.name />
</cflock>
</cfif>
</cflogin>
<cfdump var="#Session#">
<cfif GetAuthUser() NEQ "">
<cfoutput>
<form method="Post">
<input type="submit" Name="Logout" value="Logout">
</form>
</cfoutput>
</cfif>
<cfreturn true />
</cffunction>
</cfcomponent>
Copy link to clipboard
Copied
<cfset this.name = hash( getCurrentTemplatePath() ) />
Problematic, as the application's name changes per page request. Sessions are dependent on the application name. Therefore, the session will break whenever the template path changes.
To verify this hypothesis, test it with
<cfset this.name = hash("test string") />
<cfset this.applicationTimeout = createTimeSpan(1,0,0,0) />
<cfset this.sessionTimeout = createTimeSpan(0,0,20,0 ) />
Copy link to clipboard
Copied
Well no, actually the TemplatePath() is the path to Application.cfc in this case. It's an example taken from bennadel.com blog, but i also did try a fixed application name, it doesn't change anything.
Also: this exact same application behave correctly on a BlueDragon 7.1 server.
Using loginStorage="Cookie" on CF11 however seem a bit better, but there are some weirdness occasionnaly.
Copy link to clipboard
Copied
silmaril wrote:
Well no, actually the TemplatePath() is the path to Application.cfc in this case. It's an example taken from bennadel.com blog, but i also did try a fixed application name, it doesn't change anything.
You are right, I was thinking of the other one, getBaseTemplatePath(). I will have another look.
Copy link to clipboard
Copied
A possible cause of the issue is the combination,
<cfset this.sessionTimeout = createTimeSpan( 0, 0, 0, 10 )> <!--- session timeout is 10 seconds --->
<cfset THIS.loginStorage = "Session" />
<cflogin idletimeout="20"> <!--- login timeout is 20 seconds --->
This tells us that Coldfusion stores login information in the session. However, in all likelihood, the login is still active when the session times out. It is as weird as buying the ticket to watch a film between 7 PM and 9 PM, but the cinema closes between 8 PM and 9 PM.
What about testing with
<cfset this.applicationTimeout = createTimeSpan( 1, 0, 0, 0 )>
<cfset this.sessionTimeout = createTimeSpan( 0, 0, 20, 0 )> <!--- session timeout is 20 minutes --->
<cflogin idletimeout="1200"> <!--- login timeout is 20 minutes --->
Copy link to clipboard
Copied
Well, sorry i should have posted it but i tried almost all combinations i could:
* cflogin timeout shorter that session timeout
* cflogin timeout longer that session timeout
* cflogin timeout equal to session timeout
When longer or equal to session timeout i got this weird behavior,
when shorter i got another one weirder also: sometimes the <cflogin> block is being "executed" with the login/password previously used without me entering it....
I'm looking to find an CF10 install to try and compare..
Copy link to clipboard
Copied
Cflogin and session are on well-trodden ground, so any bugs there would have been found. The culprit is likely to be the code logic. I am having another look.
Copy link to clipboard
Copied
Thanks, i'm on it since last week without results ... except switching to loginStorage="Cookie" which doesn't have the problem apparently
Copy link to clipboard
Copied
What if you modify the code like this, also making it more maintainable:
Application.cfc
<cfcomponent
output="false"
hint="I define the application settings and event handlers.">
<!--- Define the application settings. --->
<cfset this.name = hash(getCurrentTemplatePath()) />
<cfset this.applicationTimeout = createTimeSpan( 1, 0, 0, 0 ) />
<cfset this.sessionTimeout = createTimeSpan( 0, 0, 20, 0 ) />
<!--- Set up the application. --->
<cfset THIS.SessionManagement = true />
<cfset THIS.ClientManagement = true />
<cfset THIS.SetClientCookies = true />
<cfset THIS.loginStorage = "Session" />
<cfset THIS.clientStorage = "sidys" />
<!--- Define the request settings. --->
<cfsetting showdebugoutput="false" />
<cffunction
name="OnRequestStart"
access="public"
returntype="boolean"
output="true"
hint="Fires at first part of page processing.">
<!--- Define arguments. --->
<cfargument
name="TargetPage"
type="string"
required="true"
/>
<cfset SetLocale("fr_FR") />
<cfif IsDefined("Form.logout") or IsDefined("URL.logout")>
<cflogout />
</cfif>
<cflogin idletimeout="1200">
<cfinclude template="form.inc" />
<cfif isDefined("cflogin.name") AND cflogin.name IS NOT "" AND cflogin.password IS NOT "">
<!--- login form submitted, with username and password filled in --->
<cfloginuser name="#cflogin.name#" Password="#cflogin.password#" roles="role">
<cfset Session.id=cflogin.name />
<cfelseif getAuthUser() IS "">
<!--- User not yet logged in --->
<cfinclude template="loginForm.cfm">
<cfabort>
</cfif>
</cflogin>
<cfif getAuthUser() NEQ "">
<cfinclude template="logoutForm.cfm">
<cfabort>
</cfif>
<cfreturn true />
</cffunction>
</cfcomponent>
loginForm.cfm
<form method="post">
<b>login :</b>
<input type="text" name="j_username" size="24" class="champ" />
<b>password :</b>
<input type="password" name="j_password" size="15" class="champ" />
<input type="submit" value="Login" class="button" name="submit" />
</form>
logoutForm.cfm
<form method="Post">
<input type="submit" Name="Logout" value="Logout">
</form>
Added edit: I removed the session lock, as I think it is unnecessary.
Copy link to clipboard
Copied
This code exemple is a very simplified exemple of my real code, it wasn't made to be manageable, only to be easier to paste
As for the session lock it was one of many attempt to fix the problem.
I will try your version.
Well no, no changes, i've reduced the timeouts to 20s since i don't wait to wait 20minutes for the session timeout and i know that even with 4h sessions
it also happens.
* You lgin, it's ok, you can redisplay (not re-POST) the logged-in page without trouble
* You let the session timeout
* You log-in again, it's ok
* You requery the application, well within the session timouet => you need to login again
* You log-in a second time and this time it's ok.
There has been changes in CF11 for handling "allowconcurrent" option, i may be mistaken but it look like that the sesion timeout and this code doesn't work together cleanly...
Copy link to clipboard
Copied
I have difficulty understanding the steps you outline in your last post. I now begin to suspect that there might be an issue with the way in which you test the login.
Could we return to the beginning? You say that the issue is:
after a session/client timeout the first login doesn't last for longer than the login submit request
Could you please let us know the following:
1) What do you mean by "the first login doesn't last for longer than the login submit request"? How do you compare them? How do you know how long the login lasts? How do you know how long the login submit request lasts?
2) What do you mean by "you can redisplay (not re-POST) the logged-in page without trouble"? What is the "logged-in page"?
3) What do you mean by "you requery the application"? Do you mean, for example, "you request an arbitrary page, test.cfm, which dumps the session"?
Copy link to clipboard
Copied
Well it's very simple in fact:
T=0: "GET /" => Got the loginForm
T=1: "POST /" => Got the application start page ("you're logged-in")
T=2: "GET /" => Got the application start page("you're logged-in")
T=31: "GET /" => Got the loginForm
T=32: "POST /" => Got the application start page ("you're logged-in")
T=33: "GET /" => Got the loginForm
T=34: "POST /" => Got the application start page ("you're logged-in")
T=35: "GET /" => Got the application start page ("you're logged-in")
The problem is the "double login" required after the session timeout (T=31 with a 2Ã s idle timeout) for the "logged-in" state to stuck accross queries.
I did put some <cfdump var=#session#> on two location (beginning of <cflogin> tag, and just after the <cflogin tag)
Copy link to clipboard
Copied
T=1: "POST /" => Got the application start page ("you're logged-in")
That is ambiguous. It is posting and getting at the same time. To avoid ambiguity, please mention in each case the page/URL you are GETting from or POSTing to. It is crucial to know the list of CFM pages in the test and the sequence in which they are requested.
Copy link to clipboard
Copied
It don't follow you, the cflogin intercept every request so all request are made to the same URL "/" as i wrote.
When you POST the login+password the <cflogin is triggered and then the page processing continue to the index.cfm page you "get" the application start page
Copy link to clipboard
Copied
Bear with me; I will rephrase the question. Are all requests in the test to the URL index.cfm? If so, does index.cfm have code similar to this:
<cfif isDefined("session.id") and session.id is not "">
you're logged-in
</cfif>
Copy link to clipboard
Copied
Are we also to assume that the page form.inc plays no role in this?
Copy link to clipboard
Copied
If you are indeed using just one page, index.cfm, to test, then leave out the last cfabort tag I suggested. That is, use the following instead
<cfif getAuthUser() NEQ "">
<cfinclude template="logoutForm.cfm">
</cfif>
Copy link to clipboard
Copied
> Bear with me; I will rephrase the question. Are all requests in the test to the URL index.cfm? If so, does index.cfm have code similar to this:
Yes exactly
> Are we also to assume that the page form.inc plays no role in this?
I was a leftover to the simplification made for the posting, it's content is similar to your "loginForm.cfm"
>If you are indeed using just one page, index.cfm, to test, then leave out the last cfabort tag I suggested. That is, use the following instead
Yes but i doesn't really matter, with your cfabort it's the "logout form" that appear/disappear and allow to see if we are in fact logged-in.
Copy link to clipboard
Copied
I created a directory and copied your code to it. The exception was that I set THIS.ClientManagement to false and commented out the lines <cfset THIS.clientStorage = "sidys" /> and <cfinclude template="form.inc" />.
The code worked as expected. The files I used in the test are shown below.
index.cfm
We are in index.cfm<br>
<cfdump var="#session#">
Application.cfc
<cfcomponent>
<!--- Define the application settings. --->
<cfset this.name = hash(getCurrentTemplatePath()) />
<cfset this.applicationTimeout = createTimeSpan( 1, 0, 0, 0 ) />
<cfset this.sessionTimeout = createTimeSpan( 0, 0, 0, 10 ) />
<!--- Set up the application. --->
<cfset THIS.SessionManagement = true />
<cfset THIS.ClientManagement = false />
<cfset THIS.SetClientCookies = true />
<cfset THIS.loginStorage = "Session" />
<!--- <cfset THIS.clientStorage = "sidys" /> --->
<!--- Define the request settings. --->
<cfsetting showdebugoutput="false" />
<cffunction
name="OnRequestStart"
access="public"
returntype="boolean"
output="true"
hint="Fires at first part of page processing.">
<!--- Define arguments. --->
<cfargument
name="TargetPage"
type="string"
required="true"
/>
<cfset SetLocale("fr_FR") />
<cfif IsDefined("Form.logout") or IsDefined("URL.logout")>
<cflogout />
</cfif>
<cflogin idletimeout="10">
<!--- <cfinclude template="form.inc" /> --->
<cfif isDefined("cflogin.name") AND cflogin.name IS NOT "" AND cflogin.password IS NOT "">
<!--- login form submitted, with username and password filled in --->
<cfloginuser name="#cflogin.name#" Password="#cflogin.password#" roles="role">
<cfset Session.id=cflogin.name />
<cfelseif getAuthUser() IS "">
<!--- User not yet logged in --->
<cfinclude template="loginForm.cfm">
<cfabort>
</cfif>
</cflogin>
<cfif getAuthUser() NEQ "">
<cfinclude template="logoutForm.cfm">
<!--- <cfabort> --->
</cfif>
<cfreturn true />
</cffunction>
</cfcomponent>
loginform.cfm
<div>
<form method="post">
<b>login :</b>
<input type="text" name="j_username" size="24" class="champ" />
<b>password :</b>
<input type="password" name="j_password" size="15" class="champ" />
<input type="submit" value="Login" class="button" name="submit" />
</form>
</div>
logoutform.cfm
<div>
<form method="Post">
<input type="submit" Name="Logout" value="Logout">
</form>
</div>
You will observe that, like you, I set the session and cflogin timeout to a low test value, 10 seconds. When I first opened the URL to index.cfm in the browser, the login form was duly displayed. I entered a name and password and submitted the form.
I got the index.cfm page again. That time it had the logout button and a dump of the session scope. The dump contained an id (my username), confirming that login was still active. When I re-requested index.cfm, repeatedly in the browser, within around 4 or 5 seconds, its contents remained unchanged. I then waited for about 15 to 20 seconds, for the login and session to time out.
I then repeated the procedure of logging in and re-requesting index.cfm every 4 or 5 seconds. I got the same result: its contents remained unchanged. That is the expected behaviour of cflogin and session.
Copy link to clipboard
Copied
I copy/pasted your example, still same result for me. Which release are your using ?
Server Product | ColdFusion |
Version | 11,0,0,289974 |
Tomcat Version | 7.0.52.0 |
Edition | Enterprise (Trial) |
Operating System | UNIX |
OS Version | 3.2.0-4-amd64 |
Adobe Driver Version | 5.1.1 (Build 0001) |
JVM Details | |
Java Version | 1.7.0_55 |
Java Vendor | Oracle Corporation |
Java Vendor URL | http://java.oracle.com/ |
Java Home | /opt/coldfusion11/jre |
Copy link to clipboard
Copied
Mine settings are:
Version: 11,0,0,289822
Tomcat Version: 7.0.52.0
Edition: Developer
Operating System: Windows 7
OS Version: 6.1
Adobe Driver Version: 5.1.1 (Build 0001)
JVM Details
Java Version: 1.7.0_51
Java Vendor: Oracle Corporation
Java Vendor URL: http://java.oracle.com/
Java Home: C:\ColdFusion11\jre
Copy link to clipboard
Copied
You will be relieved to hear, I have been able to reproduce the issue. However, only at random. I am now looking for a pattern.
Copy link to clipboard
Copied
For the time being, does it help when you replace the first tag of your login form with:
<cfoutput><form method="post" action="#cgi.SCRIPT_NAME#"></cfoutput>
Copy link to clipboard
Copied
> You will be relieved to hear, I have been able to reproduce the issue. However, only at random. I am now looking for a pattern.
Strange, it's very consistent on my side.
I will try installing on a windows host like yours.
> For the time being, does it help when you replace the first tag of your login form with:
Noope, absolutly not.
The only thing that does help is the loginStorage=Cookie mode.
Copy link to clipboard
Copied
I can reproduce it on a brand new CF11 dev edition on windows 8.1
Server Details | |
Server Product | ColdFusion |
Version | 11,0,0,289974 |
Tomcat Version | 7.0.52.0 |
Edition | Enterprise (Trial) |
Operating System | Windows 8 |
OS Version | 6.2 |
Adobe Driver Version | 5.1.1 (Build 0001) |
JVM Details | |
Java Version | 1.7.0_55 |
Java Vendor | Oracle Corporation |