@@ -207,10 +207,10 @@ public class AtmospherePushConnection implements PushConnection { | |||
String extraParams = UIConstants.UI_ID_PARAMETER + "=" | |||
+ connection.getConfiguration().getUIId(); | |||
String csrfToken = connection.getMessageHandler().getCsrfToken(); | |||
if (!csrfToken.equals(ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE)) { | |||
extraParams += "&" + ApplicationConstants.CSRF_TOKEN_PARAMETER + "=" | |||
+ csrfToken; | |||
String pushId = connection.getMessageHandler().getPushId(); | |||
if (pushId != null) { | |||
extraParams += "&" + ApplicationConstants.PUSH_ID_PARAMETER + "=" | |||
+ pushId; | |||
} | |||
// uri is needed to identify the right connection when closing | |||
@@ -526,7 +526,7 @@ public class AtmospherePushConnection implements PushConnection { | |||
JavaScriptObject config) | |||
/*-{ | |||
var self = this; | |||
config.url = uri; | |||
config.onOpen = $entry(function(response) { | |||
self.@com.vaadin.client.communication.AtmospherePushConnection::onOpen(*)(response); | |||
@@ -552,7 +552,7 @@ public class AtmospherePushConnection implements PushConnection { | |||
config.onClientTimeout = $entry(function(request) { | |||
self.@com.vaadin.client.communication.AtmospherePushConnection::onClientTimeout(*)(request); | |||
}); | |||
return $wnd.vaadinPush.atmosphere.subscribe(config); | |||
}-*/; | |||
@@ -134,6 +134,9 @@ public class MessageHandler { | |||
// will hold the CSRF token once received | |||
private String csrfToken = ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE; | |||
// holds the push identifier once received | |||
private String pushId = null; | |||
/** Timer for automatic redirect to SessionExpiredURL */ | |||
private Timer redirectTimer; | |||
@@ -350,6 +353,12 @@ public class MessageHandler { | |||
csrfToken = json | |||
.getString(ApplicationConstants.UIDL_SECURITY_TOKEN_ID); | |||
} | |||
// Get push id if present | |||
if (json.containsKey(ApplicationConstants.UIDL_PUSH_ID)) { | |||
pushId = json.getString(ApplicationConstants.UIDL_PUSH_ID); | |||
} | |||
getLogger().info(" * Handling resources from server"); | |||
if (json.containsKey("resources")) { | |||
@@ -1687,6 +1696,16 @@ public class MessageHandler { | |||
return csrfToken; | |||
} | |||
/** | |||
* Gets the push connection identifier for this session. Used when | |||
* establishing a push connection with the client. | |||
* | |||
* @return the push connection identifier string | |||
*/ | |||
public String getPushId() { | |||
return pushId; | |||
} | |||
/** | |||
* Checks whether state changes are currently being processed. Certain | |||
* operations are not allowed when the internal state of the application |
@@ -744,6 +744,8 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { | |||
*/ | |||
private final String csrfToken = UUID.randomUUID().toString(); | |||
private final String pushId = UUID.randomUUID().toString(); | |||
/** | |||
* Generate an id for the given Connector. Connectors must not call this | |||
* method more than once, the first time they need an id. | |||
@@ -1417,6 +1419,17 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { | |||
return csrfToken; | |||
} | |||
/** | |||
* Gets the push connection identifier for this session. Used when | |||
* establishing a push connection with the client. | |||
* | |||
* @return the push connection identifier string | |||
*/ | |||
public String getPushId() { | |||
assert hasLock(); | |||
return pushId; | |||
} | |||
/** | |||
* Override default deserialization logic to account for transient | |||
* {@link #pendingAccessQueue}. |
@@ -90,10 +90,10 @@ public class PushHandler { | |||
} | |||
String requestToken = resource.getRequest() | |||
.getParameter(ApplicationConstants.CSRF_TOKEN_PARAMETER); | |||
if (!VaadinService.isCsrfTokenValid(session, requestToken)) { | |||
.getParameter(ApplicationConstants.PUSH_ID_PARAMETER); | |||
if (!isPushIdValid(session, requestToken)) { | |||
getLogger().log(Level.WARNING, | |||
"Invalid CSRF token in new connection received from {0}", | |||
"Invalid identifier in new connection received from {0}", | |||
resource.getRequest().getRemoteHost()); | |||
// Refresh on client side, create connection just for | |||
// sending a message | |||
@@ -479,6 +479,25 @@ public class PushHandler { | |||
return Logger.getLogger(PushHandler.class.getName()); | |||
} | |||
/** | |||
* Checks whether a given push id matches the session's push id. | |||
* | |||
* @param session | |||
* the vaadin session for which the check should be done | |||
* @param requestPushId | |||
* the push id provided in the request | |||
* @return {@code true} if the id is valid, {@code false} otherwise | |||
*/ | |||
private static boolean isPushIdValid(VaadinSession session, | |||
String requestPushId) { | |||
String sessionPushId = session.getPushId(); | |||
if (requestPushId == null || !requestPushId.equals(sessionPushId)) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
/** | |||
* Called when a new push connection is requested to be opened by the client | |||
* |
@@ -287,6 +287,9 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler { | |||
if (session.getConfiguration().isXsrfProtectionEnabled()) { | |||
writer.write(getSecurityKeyUIDL(session)); | |||
} | |||
if (uI.getPushConfiguration().getPushMode().isEnabled()) { | |||
writer.write(getPushIdUIDL(session)); | |||
} | |||
new UidlWriter().write(uI, writer, false); | |||
writer.write("}"); | |||
@@ -310,6 +313,18 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler { | |||
+ seckey + "\","; | |||
} | |||
/** | |||
* Gets the push connection identifier as UIDL. | |||
* | |||
* @param session | |||
* the vaadin session to which the security key belongs | |||
* @return the push identifier UIDL | |||
*/ | |||
private static String getPushIdUIDL(VaadinSession session) { | |||
return "\"" + ApplicationConstants.UIDL_PUSH_ID + "\":\"" | |||
+ session.getPushId() + "\","; | |||
} | |||
private static final Logger getLogger() { | |||
return Logger.getLogger(UIInitHandler.class.getName()); | |||
} |
@@ -55,6 +55,8 @@ public class ApplicationConstants implements Serializable { | |||
public static final String UIDL_SECURITY_TOKEN_ID = "Vaadin-Security-Key"; | |||
public static final String UIDL_PUSH_ID = "Vaadin-Push-ID"; | |||
@Deprecated | |||
public static final String UPDATE_VARIABLE_INTERFACE = "v"; | |||
@Deprecated | |||
@@ -80,7 +82,7 @@ public class ApplicationConstants implements Serializable { | |||
/** | |||
* Configuration parameter giving the (in some cases relative) URL to the | |||
* web application context root. | |||
* | |||
* | |||
* @since 8.0.3 | |||
*/ | |||
public static final String CONTEXT_ROOT_URL = "contextRootUrl"; | |||
@@ -122,6 +124,11 @@ public class ApplicationConstants implements Serializable { | |||
*/ | |||
public static final String CSRF_TOKEN_PARAMETER = "v-csrfToken"; | |||
/** | |||
* Name of the parameter used to transmit the push connection identifier. | |||
*/ | |||
public static final String PUSH_ID_PARAMETER = "v-pushId"; | |||
/** | |||
* The name of the parameter used to transmit RPC invocations | |||
* |