I have a JSF 2 app that uses RichFaces 4 and Spring Security 3.1 running on Tomcat 6 (also tested on Tomcat 7). Spring Security handles the session timeout and redirects user to the login page. That works perfectly.
The problem is that AJAX calls don't seen to have the effect of extending the session lifetime the say that ordinary navigation calls do.
I've read other articles suggesting that AJAX calls don't behave the same as ordinary navigation calls and that this is why the session isn't extended (unfortunately, none of them provide a clear explanation as to why this is).
This thread suggests that a call to getSession() will do the trick. However, this is not working for me.
Instead of writing my own jquery poller I used the PrimeFaces idlemonitor as suggested here. The bean method called by the idle monitor reset calls getSession().
For testing I set the session timeout period to 4 minutes. Even though the AJAX method with getSession() is being called after two minutes the session still expires exactly 4 minutes after I navigate to that page.
Any idea what I'm doing wrong? More importantly, how would you debug this situation?
Thanks
Related
I have a basic question about JSF ManagedBeans for which I can't find a answer.
Suppose I have a bean MyBean with two methods method1 and method2 and a JSF page with a command link
<h:commandLink action="#{myBean.method1}">
</h:commandLink>
Is it possible for someone to analyse the source code of the page and call method2 instead of method1?
Answer
No, this is not possible by design.
Reasoning
Technically the client can only tell the server "The user clicked a html element with a certain id".
This event is then processed by JSF on the server-side, the component with the corresponding id is looked up and in this case the method "#{myBean.method1}" is executed.
As you can see, the client can not[!] tell the server what to do with this event.
Sources
JSF 2.2 Spec - 3.4 Event and Listener Model
Caveat
JSF is stateful and there are multiple ways to hold this state. The default is to hold state information server-side (e.g. in the users HttpSession).
Another option is to transfer (encrypted) state to and from the client. This is still conceptionally secure, but there *might* be bugs with client side state saving. Such a bug *could* be exploitable to do something like you described.
Yes, it is always possible to modify code (or markup-language) on the client-side. Your "action" will be called through some forms and/or Javascript-Methods - everything visible to experienced users.
But that's not an issue of JSF-2 only - this applies for every language which allows insights from the client side.
You shouldn't apply "security through obscurity" (https://en.wikipedia.org/wiki/Security_through_obscurity) but rather make sure, that you can handle this on the server-side.
If a user, who has access to two urls modifies url1 to url2 - that's fine, why not? (Could be bookmarked) - But YOU should take care of the modified request, if he is not allowed to access url2.
For ages I've been puzzled about why after login I sometimes don't directed to the application welcome page. I've finally figured it out (years after everyone else):
I login successfully via j_security_check and go to the welcome page
wait for session timeout
click on h:link which sends a GET request
because it's a GET and not a POST my custom ViewExpiredException
handler doesn't kick in
container security redirects to the login page because the session
has timed out. Because of the session timeout+container security the
get request (from h:link) isn't seen by the application, in either a phase listener
or filter.
I successfully login again
j_security_check redirects me to the page which triggered the
authentication, in this case the target of the GET request.
The last bit I'd not understood, I assumed it would always go to the welcome page.
My problem is that my current design requires that after login I always show the welcome page. The welcome page has a preRenderView event which sets up some context information in a session scoped bean after login and increments a few counters etc...
This context information is required by backing bean code for other pages, and presently if I don't go through the welcome page first there'll be an exception.
In terms of fixing it I've looked at the following options:
Ideally there'd be an #PostLogin method that could be called, which would cleanly solve all my problems. I use JSF (Mojarra) with Myfaces CODI but I don't see anything which does what I want.
I could add some more code to my filter, but I need to persist some data (i.e. login count), it doesn't look like a nice option. Maybe I'm wrong.
I make all the preRenderView methods of potential targets of j_security_check (pages called with GET) handle the case where they are called directly from j_seecurity_check. I can see this being what I have to do but it seems like a lot of hassle.
Write a Server Authentication Module for glassfish to override j_security_check behavior.
How is this normally handled? I've started hitting this problem after moving to GETs for simple navigation cases after years of abusing POSTs, and the custom exception handler doesn't work. If anyone has any guidance on this issue I'd appreciate it, at least I know what's going on now. Hopefully I've missed something obvious!
Thanks
O/S
Ideally there'd be an #PostLogin method that could be called, which would cleanly solve all my problems. I use JSF (Mojarra) with Myfaces CODI but I don't see anything which does what I want.
There is indeed no such thing.
I could add some more code to my filter, but I need to persist some data (i.e. login count), it doesn't look like a nice option. Maybe I'm wrong.
That would indeed be the "easiest" way. Basically:
UserPrincipal user = request.getUserPrincipal();
HttpSession session = request.getSession();
if (user != null && session.getAttribute("user") == null) {
session.setAttribute("user", user);
// First-time login. You can do your intercepting thing here.
response.sendRedirect(request.getContextPath() + "/welcome.xhtml");
}
I make all the preRenderView methods of potential targets of j_security_check (pages called with GET) handle the case where they are called directly from j_seecurity_check. I can see this being what I have to do but it seems like a lot of hassle.
That's not DRY.
Write a Server Authentication Module for glassfish to override j_security_check behavior.
Can't answer that as I've never done that.
I know that this question seems to be answered by a lot of other threads, but I can't find a solution with JSF 2.0 with Glassfish 3.0.1 for logout an user.
I tried either with a BASIC authentication and FORM authentication using j_security_check as action.
But for the logout method I can't find any of them that works.
I tried using a servlet with session.invalidate(), i used a managed bean tring to invalide the session, but nothing happened. I also tried with j_security_logout without success.
Does someone know what I can do for logout an user?
Calling session.invalidate() should work.
Your problem is probably that you used the browser back button to view a restricted page to test if logout really succeeded, but that page was actually served from the browser cache instead of straight from the webserver over a real HTTP connection.
In that case, you need to instruct the webbrowser to not cache the restricted pages. This way the browser will always request the page straight from the webserver. You can do this with help of a Filter. You can find an example in this question: Prevent user from seeing previously visited secured page after logout
We recently upgraded a major platform from jsf 1.2 to 2.0. After upgrading we're getting several ViewExpiredException errors each hour. From reading up on the topic it seems that this is an expected exception when sessions expire, however we've reviewed the access logs and we are getting these exceptions even when requests are only 5 minutes apart in some cases.
My questions are as follows:
1) Other than session expiration, what other conditions might cause ViewExpiredException?
2) The exception we're logging doesn't contain much detail about the exact condition that is causing the exception (missing session, corrupt session, unable to restore a particular component). Is there a way to introduce additional logging to find out the very specific situation that is triggering this exception in each case?
Mojarra 2.0.4-b09
Tomcat 6
Using Memcached Session Manager for session replication
Any help is appreciated. Thanks!
Other than session expiration, what other conditions might cause ViewExpiredException?
The enduser has requested/created too much views within a session and is submitting to an old view. The default max views per session is 15. In other words, if the enduser opens 16 browser windows/tabs on a page with a form within the same session and submits to the first one, then the user can get ViewExpiredException.
The max views per session is configureable in web.xml by
<context-param>
<param-name>com.sun.faces.numberOfViewsInSession</param-name>
<param-value>15</param-value>
</context-param>
See also Mojarra FAQ for other parameters.
Is there a way to introduce additional logging to find out the very specific situation that is triggering this exception in each case?
Not through JSF and/or a ViewExpiredException. The whole exception just means that the view is not present in the session anymore. This can in turn indeed have more underlying causes. Logging the session creation and destroy using a HttpSessionListener and logging the session attribute modifications by HttpSessionAttributeListener may be helpful.
Update as per the comments, pressing the browser back button on a cached page containing a form and then submitting the form thereafter could indeed also cause ViewExpiredException when the view is been expired. This can be solved in following two ways, preferably in a combination of them:
Instruct the browser to not cache the pages.
Do not use POST forms for plain page-to-page navigation.
For more detail, see this answer.
In my application I have created some locking / unlocking functionality based on the current page that the user is viewing. A user can view a page and will acquire a lock which is stored in my database, when they navigate away the lock is released and the database is updated.
I am trying to handle the situation when the user closes the browser window without logging out. They will still be holding the lock and I need that to be released and a database call needs to occur.
Is there a way to handle this in a JSF application using Spring or something else?
I know the javascript function onbeforeunload but I need to call a java method that will enable me to update the database.
The unload and beforeunload events aren't going to help you here since it's not by the specification guaranteed that any ajax request which is fired within those events is ever going to successfully hit the server. More than often, this won't.
The most reliable way is to keep the server side session lifetime very short, e.g. 1 minute and introduce an ajax poller on the page which polls within the same session to the server every minute (minus a few seconds) until the user is been inactive for more than the actual maximum session timeout. The user activity can be tested by listening on JavaScript keyboard (keyup) and mouse (click) events.
I am currently working on a two window application and needed to detect when a window is closed.
My JSF application uses ICEfaces. It provides an #WindowDisposed annotation for ViewScoped beans. With this annotation, the ViewScoped bean's #PreDestroy method will be called when the window is closed.
I have included an h:inputHidden tag in my page bound to the viewScoped bean and this works in terms of detecting the window closing and executing server side code.