diff options
author | Leif Åstrand <leif@vaadin.com> | 2012-09-28 14:58:37 +0300 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2012-09-28 16:29:26 +0000 |
commit | ca59c93fb4dbc112e5deb5f5a4b10c0c730a4be4 (patch) | |
tree | aea674d8f984b20eaf150725390f569d43f5f663 /server/src/com | |
parent | 9c31730847aebfe014b143b590ff6348d850a694 (diff) | |
download | vaadin-framework-ca59c93fb4dbc112e5deb5f5a4b10c0c730a4be4.tar.gz vaadin-framework-ca59c93fb4dbc112e5deb5f5a4b10c0c730a4be4.zip |
Move reinitialize session to VaadinService (#9638)
This change adds reinitializeSession as a static method in
VaadinService. The method is static because it affects the sessions of
all VaadinService instances that are using the underlying session.
Change-Id: Ia37567cb00e1f95aec344451299c99cb279a7275
Diffstat (limited to 'server/src/com')
6 files changed, 121 insertions, 61 deletions
diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java index 77a3018bb6..add32bf57b 100644 --- a/server/src/com/vaadin/server/VaadinService.java +++ b/server/src/com/vaadin/server/VaadinService.java @@ -23,6 +23,7 @@ import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; import java.util.Locale; import java.util.ServiceLoader; @@ -49,6 +50,9 @@ import com.vaadin.util.ReflectTools; * @since 7.0 */ public abstract class VaadinService implements Serializable { + private static final String REINITIALIZING_SESSION_MARKER = VaadinService.class + .getName() + ".reinitializing"; + private static final Method SESSION_INIT_METHOD = ReflectTools.findMethod( SessionInitListener.class, "sessionInit", SessionInitEvent.class); @@ -271,6 +275,11 @@ public abstract class VaadinService implements Serializable { } public void fireSessionDestroy(VaadinServiceSession vaadinSession) { + // Ignore if the session is being moved to a different backing session + if (vaadinSession.getAttribute(REINITIALIZING_SESSION_MARKER) == Boolean.TRUE) { + return; + } + for (UI ui : new ArrayList<UI>(vaadinSession.getUIs())) { vaadinSession.cleanupUI(ui); } @@ -619,4 +628,58 @@ public abstract class VaadinService implements Serializable { public boolean preserveUIOnRefresh(UIProvider provider, UICreateEvent event) { return provider.isPreservedOnRefresh(event); } + + /** + * Discards the current session and creates a new session with the same + * contents. The purpose of this is to introduce a new session key in order + * to avoid session fixation attacks. + * <p> + * Please note that this method makes certain assumptions about how data is + * stored in the underlying session and may thus not be compatible with some + * environments. + * + * @param request + * The Vaadin request for which the session should be + * reinitialized + */ + public static void reinitializeSession(VaadinRequest request) { + WrappedSession oldSession = request.getWrappedSession(); + + // Stores all attributes (security key, reference to this context + // instance) so they can be added to the new session + HashMap<String, Object> attrs = new HashMap<String, Object>(); + for (String name : oldSession.getAttributeNames()) { + Object value = oldSession.getAttribute(name); + if (value instanceof VaadinServiceSession) { + // set flag to avoid cleanup + VaadinServiceSession serviceSession = (VaadinServiceSession) value; + serviceSession.setAttribute(REINITIALIZING_SESSION_MARKER, + Boolean.TRUE); + } + attrs.put(name, value); + } + + // Invalidate the current session + oldSession.invalidate(); + + // Create a new session + WrappedSession newSession = request.getWrappedSession(); + + // Restores all attributes (security key, reference to this context + // instance) + for (String name : attrs.keySet()) { + Object value = attrs.get(name); + newSession.setAttribute(name, value); + + // Ensure VaadinServiceSession knows where it's stored + if (value instanceof VaadinServiceSession) { + VaadinServiceSession serviceSession = (VaadinServiceSession) value; + serviceSession.storeInSession(serviceSession.getService(), + newSession); + serviceSession + .setAttribute(REINITIALIZING_SESSION_MARKER, null); + } + } + + } } diff --git a/server/src/com/vaadin/server/VaadinServiceSession.java b/server/src/com/vaadin/server/VaadinServiceSession.java index c581a1930c..67b224df70 100644 --- a/server/src/com/vaadin/server/VaadinServiceSession.java +++ b/server/src/com/vaadin/server/VaadinServiceSession.java @@ -225,6 +225,7 @@ public class VaadinServiceSession implements HttpSessionBindingListener, // closing // Notify the service service.fireSessionDestroy(this); + session = null; } /** diff --git a/server/src/com/vaadin/server/VaadinServletSession.java b/server/src/com/vaadin/server/VaadinServletSession.java index 78f58d64fe..aa31a19c1b 100644 --- a/server/src/com/vaadin/server/VaadinServletSession.java +++ b/server/src/com/vaadin/server/VaadinServletSession.java @@ -16,12 +16,7 @@ package com.vaadin.server; -import java.util.Enumeration; -import java.util.HashMap; - -import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; -import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionBindingListener; /** @@ -39,8 +34,6 @@ import javax.servlet.http.HttpSessionBindingListener; @SuppressWarnings("serial") public class VaadinServletSession extends VaadinServiceSession { - private transient boolean reinitializingSession = false; - /** * Create a servlet service session for the given servlet service * @@ -51,60 +44,6 @@ public class VaadinServletSession extends VaadinServiceSession { super(service); } - @Override - public void valueUnbound(HttpSessionBindingEvent event) { - if (!reinitializingSession) { - // Avoid closing the application if we are only reinitializing the - // session. Closing the application would cause the state to be lost - // and a new application to be created, which is not what we want. - super.valueUnbound(event); - } - } - - /** - * Discards the current session and creates a new session with the same - * contents. The purpose of this is to introduce a new session key in order - * to avoid session fixation attacks. - */ - public void reinitializeSession() { - HttpServletRequest currentRequest = VaadinServletService - .getCurrentServletRequest(); - if (currentRequest == null) { - throw new IllegalStateException( - "Can not reinitialize session outside normal request handling."); - } - - HttpSession oldSession = getHttpSession(); - - // Stores all attributes (security key, reference to this context - // instance) so they can be added to the new session - HashMap<String, Object> attrs = new HashMap<String, Object>(); - for (Enumeration<String> e = oldSession.getAttributeNames(); e - .hasMoreElements();) { - String name = e.nextElement(); - attrs.put(name, oldSession.getAttribute(name)); - } - - // Invalidate the current session, set flag to avoid call to - // valueUnbound - reinitializingSession = true; - oldSession.invalidate(); - reinitializingSession = false; - - // Create a new session - HttpSession newSession = currentRequest.getSession(); - - // Restores all attributes (security key, reference to this context - // instance) - for (String name : attrs.keySet()) { - newSession.setAttribute(name, attrs.get(name)); - } - - // Update the "current session" variable - storeInSession(VaadinService.getCurrent(), new WrappedHttpSession( - newSession)); - } - /** * Gets the http-session application is running in. * diff --git a/server/src/com/vaadin/server/WrappedHttpSession.java b/server/src/com/vaadin/server/WrappedHttpSession.java index 1465588e08..e13a63635b 100644 --- a/server/src/com/vaadin/server/WrappedHttpSession.java +++ b/server/src/com/vaadin/server/WrappedHttpSession.java @@ -16,6 +16,11 @@ package com.vaadin.server; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Set; + import javax.servlet.http.HttpSession; /** @@ -63,4 +68,24 @@ public class WrappedHttpSession implements WrappedSession { return session; } + @Override + public Set<String> getAttributeNames() { + Enumeration<String> attributeNames = session.getAttributeNames(); + return enumerationToSet(attributeNames); + } + + // Helper shared with WrappedPortletSession + static <T> Set<T> enumerationToSet(Enumeration<T> values) { + HashSet<T> set = new HashSet<T>(); + while (values.hasMoreElements()) { + set.add(values.nextElement()); + } + return Collections.unmodifiableSet(set); + } + + @Override + public void invalidate() { + session.invalidate(); + } + } diff --git a/server/src/com/vaadin/server/WrappedPortletSession.java b/server/src/com/vaadin/server/WrappedPortletSession.java index eb07eb38f6..03c1d7ba1f 100644 --- a/server/src/com/vaadin/server/WrappedPortletSession.java +++ b/server/src/com/vaadin/server/WrappedPortletSession.java @@ -16,6 +16,8 @@ package com.vaadin.server; +import java.util.Set; + import javax.portlet.PortletSession; /** @@ -62,4 +64,14 @@ public class WrappedPortletSession implements WrappedSession { public PortletSession getPortletSession() { return session; } + + @Override + public Set<String> getAttributeNames() { + return WrappedHttpSession.enumerationToSet(session.getAttributeNames()); + } + + @Override + public void invalidate() { + session.invalidate(); + } } diff --git a/server/src/com/vaadin/server/WrappedSession.java b/server/src/com/vaadin/server/WrappedSession.java index 3973c257c8..34443239c7 100644 --- a/server/src/com/vaadin/server/WrappedSession.java +++ b/server/src/com/vaadin/server/WrappedSession.java @@ -16,6 +16,8 @@ package com.vaadin.server; +import java.util.Set; + import javax.portlet.PortletSession; import javax.servlet.http.HttpSession; @@ -66,4 +68,22 @@ public interface WrappedSession { * @see javax.portlet.PortletSession#setAttribute(String, Object) */ public void setAttribute(String name, Object value); + + /** + * Gets the current set of attribute names stored in this session. + * + * @return an unmodifiable set of the current attribute names + * + * @see HttpSession#getAttributeNames() + * @see PortletSession#getAttributeNames() + */ + public Set<String> getAttributeNames(); + + /** + * Invalidates this session then unbinds any objects bound to it. + * + * @see HttpSession#invalidate() + * @see PortletSession#invalidate() + */ + public void invalidate(); } |