Skip to content

Commit

Permalink
Add ability to set delimiters for CookieHttpSessionStrategy
Browse files Browse the repository at this point in the history
Fixes gh-615
  • Loading branch information
Rob Winch committed Sep 7, 2016
1 parent 1ead9f7 commit b79dc79
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 3 deletions.
Expand Up @@ -139,6 +139,11 @@
*/
public final class CookieHttpSessionStrategy
implements MultiHttpSessionStrategy, HttpSessionManager {
/**
* The default delimiter for both serialization and deserialization.
*/
private static final String DEFAULT_DELIMITER = " ";

private static final String SESSION_IDS_WRITTEN_ATTR = CookieHttpSessionStrategy.class
.getName().concat(".SESSIONS_WRITTEN_ATTR");

Expand All @@ -152,6 +157,17 @@ public final class CookieHttpSessionStrategy

private CookieSerializer cookieSerializer = new DefaultCookieSerializer();

/**
* The delimiter between a session alias and a session id when reading a cookie value. The default value is " ".
*/
private String deserializationDelimiter = DEFAULT_DELIMITER;

/**
* The delimiter between a session alias and a session id when writing a cookie value.
* The default is " ".
*/
private String serializationDelimiter = DEFAULT_DELIMITER;

public String getRequestedSessionId(HttpServletRequest request) {
Map<String, String> sessionIds = getSessionIds(request);
String sessionAlias = getCurrentSessionAlias(request);
Expand Down Expand Up @@ -238,9 +254,9 @@ private String createSessionCookieValue(Map<String, String> sessionIds) {
String id = entry.getValue();

buffer.append(alias);
buffer.append(" ");
buffer.append(this.serializationDelimiter);
buffer.append(id);
buffer.append(" ");
buffer.append(this.serializationDelimiter);
}
buffer.deleteCharAt(buffer.length() - 1);
return buffer.toString();
Expand Down Expand Up @@ -290,12 +306,36 @@ public void setCookieName(String cookieName) {
this.cookieSerializer = serializer;
}

/**
* Sets the delimiter between a session alias and a session id when deserializing a cookie. The default is " "
* This is useful when using <a href="https://tools.ietf.org/html/rfc6265">RFC
* 6265</a> for writing the cookies which doesn't allow for spaces in the cookie
* values.
*
* @param delimiter the delimiter to set (i.e. "_ " will try a delimeter of either "_" or " ")
*/
public void setDeserializationDelimiter(String delimiter) {
this.deserializationDelimiter = delimiter;
}

/**
* Sets the delimiter between a session alias and a session id when deserializing a cookie. The default is " ".
* This is useful when using <a href="https://tools.ietf.org/html/rfc6265">RFC
* 6265</a> for writing the cookies which doesn't allow for spaces in the cookie
* values.
*
* @param delimiter the delimiter to set (i.e. "_")
*/
public void setSerializationDelimiter(String delimiter) {
this.serializationDelimiter = delimiter;
}

public Map<String, String> getSessionIds(HttpServletRequest request) {
List<String> cookieValues = this.cookieSerializer.readCookieValues(request);
String sessionCookieValue = cookieValues.isEmpty() ? ""
: cookieValues.iterator().next();
Map<String, String> result = new LinkedHashMap<String, String>();
StringTokenizer tokens = new StringTokenizer(sessionCookieValue, " ");
StringTokenizer tokens = new StringTokenizer(sessionCookieValue, this.deserializationDelimiter);
if (tokens.countTokens() == 1) {
result.put(DEFAULT_ALIAS, tokens.nextToken());
return result;
Expand Down
Expand Up @@ -114,6 +114,18 @@ public void onNewSessionExistingSessionNewAlias() throws Exception {
.isEqualTo("0 " + existing.getId() + " new " + this.session.getId());
}

@Test
public void onNewSessionExistingSessionNewAliasCustomDelimiter() throws Exception {
this.strategy.setSerializationDelimiter("_");
Session existing = new MapSession();
setSessionCookie(existing.getId());
this.request.setParameter(
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, "new");
this.strategy.onNewSession(this.session, this.request, this.response);
assertThat(getSessionId())
.isEqualTo("0_" + existing.getId() + "_new_" + this.session.getId());
}

// gh-321
@Test
public void onNewSessionExplicitAlias() throws Exception {
Expand Down Expand Up @@ -463,6 +475,53 @@ public void getSessionIdsMulti() {
assertThat(sessionIds.get("1")).isEqualTo("b");
}

@Test
public void getSessionIdsMultiCustomDelimeter() {
this.strategy.setDeserializationDelimiter("_");
setSessionCookie("0_a_1_b");

Map<String, String> sessionIds = this.strategy.getSessionIds(this.request);
assertThat(sessionIds.size()).isEqualTo(2);
assertThat(sessionIds.get("0")).isEqualTo("a");
assertThat(sessionIds.get("1")).isEqualTo("b");
}

@Test
public void getSessionIdsMultiCustomDelimeterMigration() {
this.strategy.setDeserializationDelimiter("_ ");
this.strategy.setSerializationDelimiter("_");

// can parse the old way
setSessionCookie("0 a 1 b");

Map<String, String> sessionIds = this.strategy.getSessionIds(this.request);
assertThat(sessionIds.size()).isEqualTo(2);
assertThat(sessionIds.get("0")).isEqualTo("a");
assertThat(sessionIds.get("1")).isEqualTo("b");

// can parse the new way
this.request = new MockHttpServletRequest();
this.response = new MockHttpServletResponse();
setSessionCookie("0_a_1_b");

sessionIds = this.strategy.getSessionIds(this.request);
assertThat(sessionIds.size()).isEqualTo(2);
assertThat(sessionIds.get("0")).isEqualTo("a");
assertThat(sessionIds.get("1")).isEqualTo("b");

// writes the new way
this.request = new MockHttpServletRequest();
this.response = new MockHttpServletResponse();
Session existing = new MapSession();
setSessionCookie(existing.getId());
this.request.setParameter(
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, "new");
this.strategy.onNewSession(this.session, this.request, this.response);
assertThat(getSessionId())
.isEqualTo("0_" + existing.getId() + "_new_" + this.session.getId());

}

@Test
public void getSessionIdsDangling() {
setSessionCookie("0 a 1 b noValue");
Expand Down

0 comments on commit b79dc79

Please sign in to comment.