aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Englund <marc.englund@itmill.com>2008-11-10 14:58:17 +0000
committerMarc Englund <marc.englund@itmill.com>2008-11-10 14:58:17 +0000
commit1818fc8521fb2d08daa3044f7beee090d92e8ba2 (patch)
treeda29857d54ddb2fb34a10038a516d9913961f276
parent2e400de2e002e70012fa5ac628dff74b131c9c0b (diff)
downloadvaadin-framework-1818fc8521fb2d08daa3044f7beee090d92e8ba2.tar.gz
vaadin-framework-1818fc8521fb2d08daa3044f7beee090d92e8ba2.zip
Double cookie submit pattern impl; fixes #2198
svn changeset:5855/svn branch:trunk
-rwxr-xr-xsrc/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java9
-rw-r--r--src/com/itmill/toolkit/terminal/gwt/server/ApplicationServlet.java30
-rw-r--r--src/com/itmill/toolkit/terminal/gwt/server/CommunicationManager.java45
3 files changed, 66 insertions, 18 deletions
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java
index 827c6353de..b09a9bc08c 100755
--- a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java
+++ b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java
@@ -25,6 +25,7 @@ import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Element;
@@ -60,6 +61,8 @@ public class ApplicationConnection {
public static final String VAR_BURST_SEPARATOR = "\u001d";
+ public static final String UIDL_SECURITY_COOKIE_NAME = "com.itmill.toolkit.seckey";
+
private final HashMap resourcesMap = new HashMap();
private static Console console;
@@ -276,6 +279,10 @@ public class ApplicationConnection {
boolean forceSync) {
startRequest();
+ // cookie double submission pattern
+ requestData = Cookies.getCookie(UIDL_SECURITY_COOKIE_NAME)
+ + VAR_BURST_SEPARATOR + requestData;
+
console.log("Making UIDL Request with params: " + requestData);
String uri = getAppUri() + "UIDL" + configuration.getPathInfo();
if (repaintAll) {
@@ -637,7 +644,7 @@ public class ApplicationConnection {
}
if (html.length() != 0) {
- INotification n = new INotification(1000 * 60 * 45); // 45min
+ INotification n = new INotification(1000 * 60 * 45); //45min
n.addEventListener(new NotificationRedirect(url));
n.show(html, INotification.CENTERED_TOP,
INotification.STYLE_SYSTEM);
diff --git a/src/com/itmill/toolkit/terminal/gwt/server/ApplicationServlet.java b/src/com/itmill/toolkit/terminal/gwt/server/ApplicationServlet.java
index e7b61b094b..007843bef9 100644
--- a/src/com/itmill/toolkit/terminal/gwt/server/ApplicationServlet.java
+++ b/src/com/itmill/toolkit/terminal/gwt/server/ApplicationServlet.java
@@ -16,6 +16,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
+import java.security.GeneralSecurityException;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
@@ -26,6 +27,7 @@ import java.util.Properties;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
+import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -42,6 +44,7 @@ import com.itmill.toolkit.terminal.ParameterHandler;
import com.itmill.toolkit.terminal.Terminal;
import com.itmill.toolkit.terminal.ThemeResource;
import com.itmill.toolkit.terminal.URIHandler;
+import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
import com.itmill.toolkit.ui.Window;
/**
@@ -526,6 +529,27 @@ public class ApplicationServlet extends HttpServlet {
throw new ServletException(ee);
}
+ } catch (final GeneralSecurityException e) {
+ // TODO handle differently?
+ // Invalid security key, show session expired message for now
+ try {
+ Application.SystemMessages ci = getSystemMessages();
+ if (!UIDLrequest) {
+ // 'plain' http req - e.g. browser reload;
+ // just go ahead redirect the browser
+ response.sendRedirect(ci.getSessionExpiredURL());
+ } else {
+ // send uidl redirect
+ criticalNotification(request, response, ci
+ .getSessionExpiredCaption(), ci
+ .getSessionExpiredMessage(), ci
+ .getSessionExpiredURL());
+ }
+ request.getSession().invalidate();
+ } catch (SystemMessageException ee) {
+ throw new ServletException(ee);
+ }
+
} catch (final Throwable e) {
// if this was an UIDL request, response UIDL back to client
if (UIDLrequest) {
@@ -748,6 +772,12 @@ public class ApplicationServlet extends HttpServlet {
HttpServletResponse response, Window window, String themeName,
Application application) throws IOException, MalformedURLException {
+ // Security: double cookie submission pattern
+ Cookie secCookie = new Cookie(
+ ApplicationConnection.UIDL_SECURITY_COOKIE_NAME, request
+ .getSession().getId());
+ response.addCookie(secCookie);
+
// e.g portlets only want a html fragment
boolean fragment = (request.getAttribute(REQUEST_FRAGMENT) != null);
if (fragment) {
diff --git a/src/com/itmill/toolkit/terminal/gwt/server/CommunicationManager.java b/src/com/itmill/toolkit/terminal/gwt/server/CommunicationManager.java
index 0c7da33466..56d4559f22 100644
--- a/src/com/itmill/toolkit/terminal/gwt/server/CommunicationManager.java
+++ b/src/com/itmill/toolkit/terminal/gwt/server/CommunicationManager.java
@@ -14,6 +14,7 @@ import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.security.GeneralSecurityException;
import java.text.DateFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -216,7 +217,8 @@ public class CommunicationManager implements Paintable.RepaintRequestListener {
*/
public void handleUidlRequest(HttpServletRequest request,
HttpServletResponse response, ApplicationServlet applicationServlet)
- throws IOException, ServletException {
+ throws IOException, ServletException,
+ InvalidUIDLSecurityKeyException {
// repaint requested or session has timed out and new one is created
boolean repaintAll = (request.getParameter(GET_PARAM_REPAINT_ALL) != null)
@@ -572,7 +574,7 @@ public class CommunicationManager implements Paintable.RepaintRequestListener {
*/
private boolean handleVariables(HttpServletRequest request,
HttpServletResponse response, Application application2,
- Window window) throws IOException {
+ Window window) throws IOException, InvalidUIDLSecurityKeyException {
boolean success = true;
if (request.getContentLength() > 0) {
@@ -591,7 +593,13 @@ public class CommunicationManager implements Paintable.RepaintRequestListener {
// Manage bursts one by one
final String[] bursts = changes.split(VAR_BURST_SEPARATOR);
- for (int bi = 0; bi < bursts.length; bi++) {
+ // check security key (==sessionid, double cookie submission
+ if (!request.getSession().getId().equals(bursts[0])) {
+ throw new InvalidUIDLSecurityKeyException(
+ "Invalid UIDL security key");
+ }
+
+ for (int bi = 1; bi < bursts.length; bi++) {
// extract variables to two dim string array
final String[] tmp = bursts[bi].split(VAR_RECORD_SEPARATOR);
@@ -614,8 +622,7 @@ public class CommunicationManager implements Paintable.RepaintRequestListener {
&& variable[VAR_PID]
.equals(nextVariable[VAR_PID])) {
// we have more than one value changes in row for
- // one
- // variable owner, collect em in HashMap
+ // one variable owner, collect em in HashMap
m = new HashMap();
m.put(variable[VAR_NAME], convertVariableValue(
variable[VAR_TYPE].charAt(0),
@@ -645,9 +652,8 @@ public class CommunicationManager implements Paintable.RepaintRequestListener {
try {
owner.changeVariables(request, m);
- // Special-case of closing browser-level
- // windows: track browser-windows currently open in
- // client
+ // Special-case of closing browser-level windows:
+ // track browser-windows currently open in client
if (owner instanceof Window
&& ((Window) owner).getParent() == null) {
final Boolean close = (Boolean) m.get("close");
@@ -694,8 +700,7 @@ public class CommunicationManager implements Paintable.RepaintRequestListener {
// not interested in sending any UIDL changes back to client.
// Still we must clear component tree between bursts to ensure
// that no removed components are updated. The painting after
- // the
- // last burst is handled normally by the calling method.
+ // the last burst is handled normally by the calling method.
if (bi < bursts.length - 1) {
// We will be discarding all changes
@@ -1014,8 +1019,8 @@ public class CommunicationManager implements Paintable.RepaintRequestListener {
if (logoutUrl == null) {
logoutUrl = application.getURL().toString();
}
- // clients JS app is still running, send a special json file to
- // tell client that application has quit and where to point browser now
+ // clients JS app is still running, send a special json file to tell
+ // client that application has quit and where to point browser now
// Set the response type
response.setContentType("application/json; charset=UTF-8");
final ServletOutputStream out = response.getOutputStream();
@@ -1067,11 +1072,9 @@ public class CommunicationManager implements Paintable.RepaintRequestListener {
final ArrayList resultset = new ArrayList(dirtyPaintabletSet);
// The following algorithm removes any components that would be painted
- // as
- // a direct descendant of other components from the dirty components
- // list.
- // The result is that each component should be painted exactly once and
- // any unmodified components will be painted as "cached=true".
+ // as a direct descendant of other components from the dirty components
+ // list. The result is that each component should be painted exactly
+ // once and any unmodified components will be painted as "cached=true".
for (final Iterator i = dirtyPaintabletSet.iterator(); i.hasNext();) {
final Paintable p = (Paintable) i.next();
@@ -1299,4 +1302,12 @@ public class CommunicationManager implements Paintable.RepaintRequestListener {
return false;
}
+ private class InvalidUIDLSecurityKeyException extends
+ GeneralSecurityException {
+
+ InvalidUIDLSecurityKeyException(String message) {
+ super(message);
+ }
+
+ }
}