This guide describes how to use Spring Session to manage multiple simultaneous browser sessions (i.e Google Accounts).

1. Integrating with Spring Session

The steps to integrate with Spring Session are exactly the same as those outline in the HttpSession Guide, so we will skip to running the sample application.

2. users Sample Application

The users application demonstrates how to allow an application to manage multiple simultaneous browser sessions (i.e. Google Accounts).

2.1. Running the users Sample Application

You can run the sample by obtaining the source code and invoking the following command:

For the sample to work, you must install Redis 2.8+ on localhost and run it with the default port (6379). Alternatively, you can update the LettuceConnectionFactory to point to a Redis server.

$ ./gradlew :samples:users:tomcatRun

You should now be able to access the application at http://localhost:8080/

2.2. Exploring the users Sample Application

Try using the application. Authenticate with the following information:

  • Username rob

  • Password rob

Now click the Login button. You should now be authenticated as the user rob.

We can click on links and our user information is preserved.

  • Click on the Link link in the navigation bar at the top

  • Observe we are still authenticated as rob

Let’s add an another account.

  • Return to the Home page

  • Click on the arrow next to rob in the upper right hand corner

  • Click Add Account

The log in form is displayed again. Authenticate with the following information:

  • Username luke

  • Password luke

Now click the Login button. You should now be authenticated as the user luke.

We can click on links and our user information is preserved.

  • Click on the Link link in the navigation bar at the top

  • Observe we are still authenticated as luke

Where did our original user go? Let’s switch to our original account.

  • Click on the arrow next to luke in the upper right hand corner.

  • Click on Switch Accountrob

We are now using the session associated with rob.

3. How does it work?

Let’s take a look at how Spring Session keeps track of multiple sessions.

3.1. Managing a Single Session

Spring Session keeps track of the HttpSession by adding a value to a cookie named SESSION. For example, the SESSION cookie might have a value of:

7e8383a4-082c-4ffe-a4bc-c40fd3363c5e

3.2. Adding a Session

We can add another session by requesting a URL that contains a special parameter in it. By default the parameter name is _s. For example, the following URL would create a new session:

The parameter value does not indicate the actual session id. This is important because we never want to allow the session id to be determined by a client to avoid session fixation attacks. Additionally, we do not want the session id to be leaked since it is sent as a query parameter. Remember sensitive information should only be transmitted as a header or in the body of the request.

Rather than creating the URL ourselves, we can utilize the HttpSessionManager to do this for us. We can obtain the HttpSessionManager from the HttpServletRequest using the following:

src/main/java/sample/UserAccountsFilter.java
HttpSessionManager sessionManager = (HttpSessionManager) httpRequest
		.getAttribute(HttpSessionManager.class.getName());

We can now use it to create a URL to add another session.

src/main/java/sample/UserAccountsFilter.java
String addAlias = unauthenticatedAlias == null ? (1)
		sessionManager.getNewSessionAlias(httpRequest)
		: (2)
		unauthenticatedAlias; (3)
String addAccountUrl = sessionManager.encodeURL(contextPath, addAlias); (4)
1 We have an existing variable named unauthenticatedAlias. The value is an alias that points to an existing unauthenticated session. If no such session exists, the value is null. This ensures if we have an existing unauthenticated session that we use it instead of creating a new session.
2 If all of our sessions are already associated to a user, we create a new session alias.
3 If there is an existing session that is not associated to a user, we use its session alias.
4 Finally, we create the add account URL. The URL contains a session alias that either points to an existing unauthenticated session or is an alias that is unused thus signaling to create a new session associated to that alias.

Now our SESSION cookie looks something like this:

0 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e 1 1d526d4a-c462-45a4-93d9-84a39b6d44ad

Such that:

  • There is a session with the id 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e

    • The alias for this session is 0. For example, if the URL is http://localhost:8080/?_s=0 this alias would be used.

    • This is the default session. This means that if no session alias is specified, then this session is used. For example, if the URL is http://localhost:8080/ this session would be used.

  • There is a session with the id 1d526d4a-c462-45a4-93d9-84a39b6d44ad

    • The alias for this session is 1. If the session alias is 1, then this session is used. For example, if the URL is http://localhost:8080/?_s=1 this alias would be used.

3.3. Automatic Session Alias Inclusion with encodeURL

The nice thing about specifying the session alias in the URL is that we can have multiple tabs open with different active sessions. The bad thing is that we need to include the session alias in every URL of our application. Fortunately, Spring Session will automatically include the session alias in any URL that passes through HttpServletResponse#encodeURL(java.lang.String)

This means that if you are using standard tag libraries the session alias is automatically included in the URL. For example, if we are currently using the session with the alias of 1, then the following:

src/main/webapp/index.jsp
  -->
<c:url value="/link.jsp" var="linkUrl"/>
<a id="navLink" href="${linkUrl}">Link</a>

will output a link of:

<a id="navLink" href="/link.jsp?_s=1">Link</a>