Re: [securityfilter-user] SecurityFilter doing authentication upon logout?
Brought to you by:
chris_schultz,
maxcooper
|
From: Christopher S. <ch...@ch...> - 2009-05-07 15:41:34
|
Matt,
On 5/5/2009 6:51 PM, Matthew Hixson wrote:
> We have a method that updates the database with the last time that a
> user logs in. I put a Thread.dumpStack() call in my method,
> updateLastLogin(). The problem I have is that upon logout execution
> ends up passing through this method again which, of course, has the
> result of logging to the database the time that the user logged out.
That's definitely odd. What version of sf are you using?
> While logging in the stack trace looks like this.
>
> java.lang.Exception: Stack trace
> at java.lang.Thread.dumpStack(Thread.java:1176)
> at mycompany.SpecialAuthenticator.updateLastLogin(SpecialAuthenticator.java:36)
> at com.mycompany.authentication.SARealm.authenticate(SARealm.java:140)
> at org.securityfilter.realm.catalina.CatalinaRealmAdapter.authenticate(CatalinaRealmAdapter.java:95)
> at org.securityfilter.authenticator.FormAuthenticator.processLogin(FormAuthenticator.java:297)
> at org.securityfilter.filter.SecurityFilter.doFilter(SecurityFilter.java:144)
> at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
> [...]
[snip]
> While logging out it produces this:
>
> java.lang.Exception: Stack trace
> at java.lang.Thread.dumpStack(Thread.java:1176)
> at mycompany.SpecialAuthenticator.updateLastLogin(SpecialAuthenticator.java:36)
> at com.mycompany.authentication.SARealm.authenticate(SARealm.java:140)
> at org.securityfilter.realm.catalina.CatalinaRealmAdapter.authenticate(CatalinaRealmAdapter.java:95)
> at org.securityfilter.authenticator.FormAuthenticator.processLogin(FormAuthenticator.java:284)
> at org.securityfilter.filter.SecurityFilter.doFilter(SecurityFilter.java:144)
> at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
> [...]
Hmm... the line numbers are different in the call to
CatalinaRealmAdapter.authenticate from FormAuthenticator.processLogin.
Have you been hacking the sf code yourself, or is everything as you got
it from the original dist package?
> So, why does
> org.securityfilter.authenticator.FormAuthenticator.processLogin() end
> up getting called when the user is logging out? My relevant part of
> securityfilter-config.xml looks like:
>
> <login-config>
> <auth-method>FORM</auth-method>
> <form-login-config>
> <form-login-page>/login.jsp</form-login-page>
> <form-error-page>/login.jsp?err=1</form-error-page>
> <form-default-page>/members/index.jsp</form-default-page>
> <form-logout-page>/logout.jsp</form-logout-page>
What about your <security-constraint> sections?
> <!-- remember-me config -->
Does disabling <remember-me> have any effect on this behavior?
> I put some debug code into my /logout.jsp to see if that were somehow
> triggering something, but the stack trace happens before execution
> even enters logout.jsp.
Right: the filter executes before any servlet (or JSP) code does.
> Any thoughts on how I can prevent my Realm's authenticate() method
> being called upon logout? And am I incorrect in assuming that
> authenticate() should only be called upon initial login?
Generally, yes. Don't be fooled by the call to processLogin: this method
is called to /determine/ if the request is for a login and take
appropriate actions.
The FormAuthenticator first checks to see if you are using a persistent
log manager (you are) and uses the remembered credentials for
authentication (that's on line 284, as in your second stack trace). Your
second case appears to match this.
Whether you are using a persistent manager or not, FormAuthenticator
continues with the standard login mechanism (which appears to be shown
in your second stack trace). The request is checked (endsWith) against
the loginSubmitPattern which defaults to "/j_security_check". What does
your <filter> configuration look like for sf? Are you passing-in any
<filter-init-param>s?
Can you post the URLs you are using that end up with stack traces #1 and
#2? Is there any forwarding or redirecting going on?
I suspect that you have "persistent logins" enabled and so when you hit
logout.jsp, you are being re-logged-in using the persistent manager.
Although the persistent manager is supposed to forget your login
/before/ trying to log you in again.
I think there might be a bug in the persistent login manager, because
the rememberingLogin() method is this:
if (getCookieValue(request.getCookies(), COOKIE_REMEMBERME,
"false").equals("true")) {
return true;
} else {
return false;
}
During a logout request, any persistent login cookies will be sent along
with the request as usual. The logout will trigger the persistent
manager to forget your login. The subsequent login check uses the cookie
/still in the request/ to log you back in. Duh.
No offense to the original authors of this code, but I somewhat recently
inherited this project, and I've never used the PersistentManager
myself. It seems like the PersistentManager has a relatively big bug,
here, in that it is not possible to log out. :)
Are you willing to recompile sf? If so, try making the following changes:
1. In DefaultPersistentManager.forgetLogin, add this code:
request.setAttribute("persistentLoginManager.logout", Boolean.TRUE);
2. Change DefaultPersistentManager.rememberingLogin to this:
return getCookieValue(request.getCookies(),
COOKIE_REMEMBERME,
"false").equals("true"))
&&
!Boolean.TRUE.equals(request.getAttribute("persistentManager.logout"))
;
See if that fixes your logout problem.
-chris
|