Browse Source

Use separate identifier for push connections

Closes #8700
tags/8.1.0.alpha5^0
Aleksi Hietanen 7 years ago
parent
commit
a4a4d9e064

+ 6
- 6
client/src/main/java/com/vaadin/client/communication/AtmospherePushConnection.java View File

String extraParams = UIConstants.UI_ID_PARAMETER + "=" String extraParams = UIConstants.UI_ID_PARAMETER + "="
+ connection.getConfiguration().getUIId(); + 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 // uri is needed to identify the right connection when closing
JavaScriptObject config) JavaScriptObject config)
/*-{ /*-{
var self = this; var self = this;
config.url = uri; config.url = uri;
config.onOpen = $entry(function(response) { config.onOpen = $entry(function(response) {
self.@com.vaadin.client.communication.AtmospherePushConnection::onOpen(*)(response); self.@com.vaadin.client.communication.AtmospherePushConnection::onOpen(*)(response);
config.onClientTimeout = $entry(function(request) { config.onClientTimeout = $entry(function(request) {
self.@com.vaadin.client.communication.AtmospherePushConnection::onClientTimeout(*)(request); self.@com.vaadin.client.communication.AtmospherePushConnection::onClientTimeout(*)(request);
}); });
return $wnd.vaadinPush.atmosphere.subscribe(config); return $wnd.vaadinPush.atmosphere.subscribe(config);
}-*/; }-*/;



+ 19
- 0
client/src/main/java/com/vaadin/client/communication/MessageHandler.java View File

// will hold the CSRF token once received // will hold the CSRF token once received
private String csrfToken = ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE; private String csrfToken = ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE;


// holds the push identifier once received
private String pushId = null;

/** Timer for automatic redirect to SessionExpiredURL */ /** Timer for automatic redirect to SessionExpiredURL */
private Timer redirectTimer; private Timer redirectTimer;


csrfToken = json csrfToken = json
.getString(ApplicationConstants.UIDL_SECURITY_TOKEN_ID); .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"); getLogger().info(" * Handling resources from server");


if (json.containsKey("resources")) { if (json.containsKey("resources")) {
return csrfToken; 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 * Checks whether state changes are currently being processed. Certain
* operations are not allowed when the internal state of the application * operations are not allowed when the internal state of the application

+ 13
- 0
server/src/main/java/com/vaadin/server/VaadinSession.java View File

*/ */
private final String csrfToken = UUID.randomUUID().toString(); 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 * Generate an id for the given Connector. Connectors must not call this
* method more than once, the first time they need an id. * method more than once, the first time they need an id.
return csrfToken; 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 * Override default deserialization logic to account for transient
* {@link #pendingAccessQueue}. * {@link #pendingAccessQueue}.

+ 22
- 3
server/src/main/java/com/vaadin/server/communication/PushHandler.java View File

} }


String requestToken = resource.getRequest() 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, getLogger().log(Level.WARNING,
"Invalid CSRF token in new connection received from {0}",
"Invalid identifier in new connection received from {0}",
resource.getRequest().getRemoteHost()); resource.getRequest().getRemoteHost());
// Refresh on client side, create connection just for // Refresh on client side, create connection just for
// sending a message // sending a message
return Logger.getLogger(PushHandler.class.getName()); 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 * Called when a new push connection is requested to be opened by the client
* *

+ 15
- 0
server/src/main/java/com/vaadin/server/communication/UIInitHandler.java View File

if (session.getConfiguration().isXsrfProtectionEnabled()) { if (session.getConfiguration().isXsrfProtectionEnabled()) {
writer.write(getSecurityKeyUIDL(session)); writer.write(getSecurityKeyUIDL(session));
} }
if (uI.getPushConfiguration().getPushMode().isEnabled()) {
writer.write(getPushIdUIDL(session));
}
new UidlWriter().write(uI, writer, false); new UidlWriter().write(uI, writer, false);
writer.write("}"); writer.write("}");


+ seckey + "\","; + 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() { private static final Logger getLogger() {
return Logger.getLogger(UIInitHandler.class.getName()); return Logger.getLogger(UIInitHandler.class.getName());
} }

+ 8
- 1
shared/src/main/java/com/vaadin/shared/ApplicationConstants.java View File



public static final String UIDL_SECURITY_TOKEN_ID = "Vaadin-Security-Key"; public static final String UIDL_SECURITY_TOKEN_ID = "Vaadin-Security-Key";


public static final String UIDL_PUSH_ID = "Vaadin-Push-ID";

@Deprecated @Deprecated
public static final String UPDATE_VARIABLE_INTERFACE = "v"; public static final String UPDATE_VARIABLE_INTERFACE = "v";
@Deprecated @Deprecated
/** /**
* Configuration parameter giving the (in some cases relative) URL to the * Configuration parameter giving the (in some cases relative) URL to the
* web application context root. * web application context root.
*
*
* @since 8.0.3 * @since 8.0.3
*/ */
public static final String CONTEXT_ROOT_URL = "contextRootUrl"; public static final String CONTEXT_ROOT_URL = "contextRootUrl";
*/ */
public static final String CSRF_TOKEN_PARAMETER = "v-csrfToken"; 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 * The name of the parameter used to transmit RPC invocations
* *

Loading…
Cancel
Save