Why shouldn't I destroy http session on user logout? - jsf

Is there any good reason not to simply destroy the HTTP session like:
FacesContext facesContext = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(false);
session.invalidate();
instead of just deauthenticating the user and make sure to clean user data from the session scoped beans?

You have to do both. Deauthenticating the user can depend on your implementation. If you call out to a third party system to obtain a security token for a user, chances are you have to call back again to invalidate the token.
You also have to invalidate the HttpSession. Invalidating the session will release all session scoped beans. It also releases JSF view states and component trees for pages visited during the user's session. These can make the session sizeable and not invalidating will leave the heap full of sessions waiting to timeout and that have a negative impact on the server's capacity.
BTW, you can invalidate the session without the need to obtain the HttpSession, like so:
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();

Find the answer in Oracle documentation:
The session.invalidate() method, which is often used to log out a
user, only invalidates the current session for a user—the user's
authentication information still remains valid and is stored in the
context of the server or virtual host. If the server or virtual host
is hosting only one Web application, the session.invalidate() method,
in effect, logs out the user.
http://docs.oracle.com/cd/E11035_01/wls100/webapp/sessions.html#wp150374

Related

When is the JSESSIONID cookie added to the response

I have a JSF 2.0 application, let's call it "MyApp", with a SessionScoped bean that uses the below code to get the session and set the path on init...
HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest(); //Get request from external context
HttpSession session = request.getSession(false); //Get session and don't create one if it doesn't exist
session.getServletContext().getSessionCookieConfig().setPath(""); //Set the path in the session's cookie
My problem is that the updated path ("") doesn't show up in the response session cookie, JSESSIONID, until the second request to the application. The first request gets a JSESSIONID cookie in the response with the default path, which includes the application's root context ("/MyApp"). If I reload the page, this second request will get a response with a JSESSIONID cookie that includes the updated path ("").
I can't seem to find any documentation on when the default JSESSIONID cookie is created and added to the response. I'm not sure if the updated session path is being set in the first response's JSESSIONID cookie or if it's being set and overridden by the page's default JSESSIONID cookie.
Questions:
When does the default JSESSIONID cookie get added to the response?
Is it possible to disable the page's default JSESSIONID cookie from being created?
When does the default JSESSIONID cookie get added to the response?
When the HTTP session is created for the first time. E.g. when JSF needs to put a newly created session scoped bean in there. So if you're writing some code in such a bean which should manipulate the session, then you're basically already too late.
Your code snippet is also a strong evidence for it. If the session was really not created, then request.getSession(false) would have returned null and subsequently, calling session.getServletContext() would have thrown a NullPointerException and you'd have asked a very different question.
Is it possible to disable the page's default JSESSIONID cookie from being created?
I believe you're asking the wrong question. You actually want to ask how to set the session cookie path the right way.
You're supposed to configure the session cookie path in web.xml as below:
<session-config>
<cookie-config>
<path>/</path>
</cookie-config>
</session-config>
If you really intend to do it programmatically for some unclear reason which is not elaborated in the question, then you should be doing this before the HTTP session is created for the first time. In other words, you should absolutely not be doing this in a session scoped JSF managed bean, nor be grabbing the needed ServletContext from the HttpSession itself.
Most sensible place would be a servlet context listener or, if you really need it to be "JSF-ish", then an eagerly initialized application scoped bean. Please note that this is an application-wide setting, not a session-wide setting. It being a property of ServletContext (and not of HttpSession) already hints that. Thus, once you set it, it affects all newly created session cookies. Depending on the concrete functional requirement which you told nothing about, there may be better ways. E.g. an additional cookie.

How to keep Session Alive beyond its MaxInactive interval

I am Switching between two different Dynamic web application through Links.But if i am working on one application for long time then others application session expires and i got redirected to login page, Is there any method to keep session alive beyond maxInactive time interval while i am working on other application page
There are two options-
If both applications requires single sign on feature (like we login to gmail, then all google services are accessible), you can use tomcat clustering and share session accross cluster. Both your apps will be part of the cluster.
A simple work aroud would be to set a heartbeat ajax request in each application. Use JavaScript's timeout function and send ajax request to servlet after a fix interval.
You can anyway update MaxInactiveInterval of server at runtime, there is this method setMaxInactiveInterval available for HTTPsession class object.
Hope this helps. :)
I can think of one option here that is to manage your own Session Pool. You can save the session object in ArrayList<HttpSession> whenever you create new session. And send that session id to your another application. When you return to previous app, you send back session id. And if you find session dead then find that session in your Session Pool by session id and create new session. In new session set attributes of the previous session object.
Hope this might be useful.

How to create, access and destroy session in JSF managed bean?

Currently, I am creating a web application for an online shopping cart and I need to maintain session on each jsf page..
My questions are :
How can I create and destroy session in managed bean
How can I access value stored in session variable? Like this?
FacesContext.getCurrentInstance().getExternalContext().getSessionMap.put("key",object);
How can I destroy a session in jsf
I also need to destroy the session using session.invalidate() but i am failed !!
How can I create and destroy session in managed bean
You don't need to create it yourself. The servletcontainer will do it automatically for you on demand. In other words, whenever you (or JSF) need to set an object in the session scope, then the servletcontainer will automatically create the session. In a JSF web application, this will happen when you
Reference a #SessionScoped or #ViewScoped managed bean for the first time.
Obtain the session by ExternalContext#getSession(), passing true for the first time.
Store an object in session map by ExternalContext#getSessionMap() for the first time.
Return a page with a <h:form> for the first time while the state saving method is set to "server".
You can destroy the session by ExternalContext#invalidateSession(). E.g.
public String logout() {
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "login?faces-redirect=true";
}
Remember to send a redirect afterwards, because the session objects are still available in the response of the current request, but not anymore in the next request.
How can I access value stored in session variable?
Just make it a property of a #SessionScoped managed bean. Alternatively, you can also manually manipulate the ExternalContext#getSessionMap(), yes.
How can I destroy a session in jsf
This is already answered in the first question.
See also:
How do servlets work? Instantiation, sessions, shared variables and multithreading
Basic steps for starting session in jsf
How to choose the right bean scope?

Looking for the code to generate jsessionid

I am looking for the default codebase for creating jsessionids. It may vary from instance to instance, but I can't seem to find it on the net, just explanations of how to change/set it.
Thanks
JSESSIONID cookie is created/sent when session is created. Session is created when your code calls request.getSession() or request.getSession(true) for the first time. If you just want get session, but not create it if it doesn't exists, use request.getSession(false) -- this will return you a session or null. In this case, new session is not created, and JSESSIONID cookie is not sent. (This also means that session isn't necessarily created on first request... you and your code is in control when the session is created)
Sessions are per-context:
SRV.7.3 Session Scope
HttpSession objects must be scoped at the application (or servlet context) level. The underlying mechanism, such as the cookie used to establish the session, can be the same for different contexts, but the object referenced, including the attributes in that object, must never be shared between contexts by the container.

Spring Security RememberMe Services with Session Cookie

I am using Spring Security's RememberMe Services to keep a user authenticated.
I would like to find a simple way to have the RememberMe cookie set as a session cookie rather than with a fixed expiration time. For my application, the cookie should persist until the user closes the browser.
Any suggestions on how to best implement this? Any concerns on this being a potential security problem?
The primary reason for doing so is that with a cookie-based token, any of the servers behind our load balancer can service a protected request without relying on the user's Authentication to be stored in an HttpSession. In fact, I have explicitly told Spring Security to never create sessions using the namespace. Further, we are using Amazon's Elastic Load Balancing, and so sticky sessions are not supported.
NB: Although I am aware that as of Apr. 08, Amazon now supports sticky sessions, I still do not want to use them for a handful of other reasons. Namely that the untimely demise of one server would still cause the loss of sessions for all users associated with it.
http://aws.amazon.com/about-aws/whats-new/2010/04/08/support-for-session-stickiness-in-elastic-load-balancing/
Spring Security 3 does not offer configuration of how the cookie is generated. You have to override the default behaviour:
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices;
/** Cookie expires on session. */
public class PersistentTokenBasedRememberMeServicesCustom extends
PersistentTokenBasedRememberMeServices {
/** only needed because super throws exception. */
public PersistentTokenBasedRememberMeServicesCustom() throws Exception {
super();
}
/** Copy of code of inherited class + setting cookieExpiration, */
#Override
protected void setCookie(String[] tokens, int maxAge,
HttpServletRequest request, HttpServletResponse response) {
String cookieValue = encodeCookie(tokens);
Cookie cookie = new Cookie(getCookieName(), cookieValue);
//cookie.setMaxAge(maxAge);
cookie.setPath("/");
cookie.setSecure(false); // no getter available in super, so always false
response.addCookie(cookie);
}
}
Make sure, you use this customized PersistentTokenBasedRememberMeServices for you're rememberMeService by adding the class name to it's bean configuration:
<beans:bean id="rememberMeServices"
class="my.custom.spring.PersistentTokenBasedRememberMeServicesCustom"/>
To have session work properly with load balancing I would have your session data stored in a sql database.
The cookie should always be a random value that expire. There are cases where you can store state as a cookie value and it not be a secuirty hazard, such as the users preferred language, but this should be avoided as much as possible. Turning HttpOnlyCookies on, is a great idea.
Read A3: "Broken Authentication and Session Management" in the OWASP top 10 for 2010. One important point in this section is that https must be used for the entire session. If the session is lasting for a very long time, then this is even more important.
Also keep in mind that "Remember Me" creates a large window in which an attacker can "ride" on the session. This gives an attacker a very long time (Months?) in which he can deliver a CSRF attack. Even if you have CSRF protection an attacker can still ride on a session with XSS and XmlHttpRequest (HttpOnlyCookies will prevent a full hijack). "Remember Me" makes other threats like xss, csrf, sniffing more serious. As long as these vulnerabilities have been addressed, then you shouldn't have a problem with real world hackers.
The easiest (and secure) approach to implement a "remember me" feature would be to modify the session timeout to make it very large (a few months). If the "remember me" checkbox is unchecked then store a session variable with a new timeout (1 day from login). Keep in mind that even if the cookie is deleted by the browser when it is closed the session still is active on the server side. If the session id stolen, then it can still be used.

Resources