Align HttpSessionStrategy with WebSessionIdResolver
This commit simplifies `HttpSessionStrategy` API by aligning it with Spring Framework's `WebSessionIdResolver`. As a part of this, support for managing multiple users' sessions has been removed. Closes gh-275 Closes gh-362
This commit is contained in:
@@ -42,7 +42,6 @@ import org.springframework.session.web.http.CookieHttpSessionStrategy;
|
||||
import org.springframework.session.web.http.CookieSerializer;
|
||||
import org.springframework.session.web.http.DefaultCookieSerializer;
|
||||
import org.springframework.session.web.http.HttpSessionStrategy;
|
||||
import org.springframework.session.web.http.MultiHttpSessionStrategy;
|
||||
import org.springframework.session.web.http.SessionEventHttpSessionListenerAdapter;
|
||||
import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -127,16 +126,11 @@ public class SpringHttpSessionConfiguration implements ApplicationContextAware {
|
||||
SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<>(
|
||||
sessionRepository);
|
||||
sessionRepositoryFilter.setServletContext(this.servletContext);
|
||||
if (this.httpSessionStrategy instanceof MultiHttpSessionStrategy) {
|
||||
sessionRepositoryFilter.setHttpSessionStrategy(
|
||||
(MultiHttpSessionStrategy) this.httpSessionStrategy);
|
||||
}
|
||||
else {
|
||||
sessionRepositoryFilter.setHttpSessionStrategy(this.httpSessionStrategy);
|
||||
}
|
||||
sessionRepositoryFilter.setHttpSessionStrategy(this.httpSessionStrategy);
|
||||
return sessionRepositoryFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
if (ClassUtils.isPresent(
|
||||
|
||||
@@ -16,20 +16,10 @@
|
||||
|
||||
package org.springframework.session.web.http;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.web.http.CookieSerializer.CookieValue;
|
||||
@@ -68,222 +58,38 @@ import org.springframework.session.web.http.CookieSerializer.CookieValue;
|
||||
* Set-Cookie: SESSION=f81d4fae-7dec-11d0-a765-00a0c91e6bf6; Expires=Thur, 1 Jan 1970 00:00:00 GMT; Secure; HttpOnly
|
||||
* </pre>
|
||||
*
|
||||
* <h2>Supporting Multiple Simultaneous Sessions</h2>
|
||||
*
|
||||
* <p>
|
||||
* By default multiple sessions are also supported. Once a session is established with the
|
||||
* browser, another session can be initiated by specifying a unique value for the
|
||||
* {@link #setSessionAliasParamName(String)}. For example, a request to:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* GET /messages/?_s=1416195761178 HTTP/1.1
|
||||
* Host: example.com
|
||||
* Cookie: SESSION=f81d4fae-7dec-11d0-a765-00a0c91e6bf6
|
||||
* </pre>
|
||||
*
|
||||
* Will result in the following response:
|
||||
*
|
||||
* <pre>
|
||||
* HTTP/1.1 200 OK
|
||||
* Set-Cookie: SESSION="0 f81d4fae-7dec-11d0-a765-00a0c91e6bf6 1416195761178 8a929cde-2218-4557-8d4e-82a79a37876d"; Expires=Thur, 1 Jan 1970 00:00:00 GMT; Secure; HttpOnly
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* To use the original session a request without the HTTP parameter u can be made. To use
|
||||
* the new session, a request with the HTTP parameter _s=1416195761178 can be used. By
|
||||
* default URLs will be rewritten to include the currently selected session.
|
||||
* </p>
|
||||
*
|
||||
* <h2>Selecting Sessions</h2>
|
||||
*
|
||||
* <p>
|
||||
* Sessions can be managed by using the HttpSessionManager and SessionRepository. If you
|
||||
* are not using Spring in the rest of your application you can obtain a reference from
|
||||
* the HttpServletRequest attributes. An example is provided below:
|
||||
* </p>
|
||||
*
|
||||
* <code>
|
||||
* HttpSessionManager sessionManager =
|
||||
* (HttpSessionManager) req.getAttribute(HttpSessionManager.class.getName());
|
||||
* SessionRepository<Session> repo =
|
||||
* (SessionRepository<Session>) req.getAttribute(SessionRepository.class.getName());
|
||||
*
|
||||
* String currentSessionAlias = sessionManager.getCurrentSessionAlias(req);
|
||||
* Map<String, String> sessionIds = sessionManager.getSessionIds(req);
|
||||
* String newSessionAlias = String.valueOf(System.currentTimeMillis());
|
||||
*
|
||||
* String contextPath = req.getContextPath();
|
||||
* List<Account> accounts = new ArrayList<>();
|
||||
* Account currentAccount = null; for(Map.Entry<String, String> entry :
|
||||
* sessionIds.entrySet()) { String alias = entry.getKey(); String sessionId =
|
||||
* entry.getValue();
|
||||
* </code>
|
||||
*
|
||||
* Session session = repo.findById(sessionId); if(session == null) { continue; }
|
||||
*
|
||||
* String username = session.getAttribute("username"); if(username == null) {
|
||||
* newSessionAlias = alias; continue; }
|
||||
*
|
||||
* String logoutUrl = sessionManager.encodeURL("./logout", alias); String switchAccountUrl
|
||||
* = sessionManager.encodeURL("./", alias); Account account = new Account(username,
|
||||
* logoutUrl, switchAccountUrl); if(currentSessionAlias.equals(alias)) { currentAccount =
|
||||
* account; } else { accounts.add(account); } }
|
||||
*
|
||||
* req.setAttribute("currentAccount", currentAccount); req.setAttribute("addAccountUrl",
|
||||
* sessionManager.encodeURL(contextPath, newSessionAlias)); req.setAttribute("accounts",
|
||||
* accounts); }
|
||||
*
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Vedran Pavic
|
||||
* @since 1.0
|
||||
*/
|
||||
public final class CookieHttpSessionStrategy
|
||||
implements MultiHttpSessionStrategy, HttpSessionManager {
|
||||
/**
|
||||
* The default delimiter for both serialization and deserialization.
|
||||
*/
|
||||
private static final String DEFAULT_DELIMITER = " ";
|
||||
public final class CookieHttpSessionStrategy implements HttpSessionStrategy {
|
||||
|
||||
private static final String SESSION_IDS_WRITTEN_ATTR = CookieHttpSessionStrategy.class
|
||||
.getName().concat(".SESSIONS_WRITTEN_ATTR");
|
||||
|
||||
static final String DEFAULT_ALIAS = "0";
|
||||
|
||||
static final String DEFAULT_SESSION_ALIAS_PARAM_NAME = "_s";
|
||||
|
||||
private static final Pattern ALIAS_PATTERN = Pattern.compile("^[\\w-]{1,50}$");
|
||||
|
||||
private String sessionParam = DEFAULT_SESSION_ALIAS_PARAM_NAME;
|
||||
private static final String WRITTEN_SESSION_ID_ATTR = CookieHttpSessionStrategy.class
|
||||
.getName().concat(".WRITTEN_SESSION_ID_ATTR");
|
||||
|
||||
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);
|
||||
return sessionIds.get(sessionAlias);
|
||||
}
|
||||
|
||||
public String getCurrentSessionAlias(HttpServletRequest request) {
|
||||
if (this.sessionParam == null) {
|
||||
return DEFAULT_ALIAS;
|
||||
}
|
||||
String u = request.getParameter(this.sessionParam);
|
||||
if (u == null) {
|
||||
return DEFAULT_ALIAS;
|
||||
}
|
||||
if (!ALIAS_PATTERN.matcher(u).matches()) {
|
||||
return DEFAULT_ALIAS;
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
public String getNewSessionAlias(HttpServletRequest request) {
|
||||
Set<String> sessionAliases = getSessionIds(request).keySet();
|
||||
if (sessionAliases.isEmpty()) {
|
||||
return DEFAULT_ALIAS;
|
||||
}
|
||||
long lastAlias = Long.decode(DEFAULT_ALIAS);
|
||||
for (String alias : sessionAliases) {
|
||||
long selectedAlias = safeParse(alias);
|
||||
if (selectedAlias > lastAlias) {
|
||||
lastAlias = selectedAlias;
|
||||
}
|
||||
}
|
||||
return Long.toHexString(lastAlias + 1);
|
||||
}
|
||||
|
||||
private long safeParse(String hex) {
|
||||
try {
|
||||
return Long.decode("0x" + hex);
|
||||
}
|
||||
catch (NumberFormatException notNumber) {
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public List<String> getRequestedSessionIds(HttpServletRequest request) {
|
||||
return this.cookieSerializer.readCookieValues(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewSession(Session session, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
Set<String> sessionIdsWritten = getSessionIdsWritten(request);
|
||||
if (sessionIdsWritten.contains(session.getId())) {
|
||||
String sessionId = session.getId();
|
||||
if (sessionId.equals(request.getAttribute(WRITTEN_SESSION_ID_ATTR))) {
|
||||
return;
|
||||
}
|
||||
sessionIdsWritten.add(session.getId());
|
||||
|
||||
Map<String, String> sessionIds = getSessionIds(request);
|
||||
String sessionAlias = getCurrentSessionAlias(request);
|
||||
sessionIds.put(sessionAlias, session.getId());
|
||||
|
||||
String cookieValue = createSessionCookieValue(sessionIds);
|
||||
request.setAttribute(WRITTEN_SESSION_ID_ATTR, sessionId);
|
||||
this.cookieSerializer
|
||||
.writeCookieValue(new CookieValue(request, response, cookieValue));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Set<String> getSessionIdsWritten(HttpServletRequest request) {
|
||||
Set<String> sessionsWritten = (Set<String>) request
|
||||
.getAttribute(SESSION_IDS_WRITTEN_ATTR);
|
||||
if (sessionsWritten == null) {
|
||||
sessionsWritten = new HashSet<>();
|
||||
request.setAttribute(SESSION_IDS_WRITTEN_ATTR, sessionsWritten);
|
||||
}
|
||||
return sessionsWritten;
|
||||
}
|
||||
|
||||
private String createSessionCookieValue(Map<String, String> sessionIds) {
|
||||
if (sessionIds.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
if (sessionIds.size() == 1 && sessionIds.keySet().contains(DEFAULT_ALIAS)) {
|
||||
return sessionIds.values().iterator().next();
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Map.Entry<String, String> entry : sessionIds.entrySet()) {
|
||||
String alias = entry.getKey();
|
||||
String id = entry.getValue();
|
||||
|
||||
sb.append(alias);
|
||||
sb.append(this.serializationDelimiter);
|
||||
sb.append(id);
|
||||
sb.append(this.serializationDelimiter);
|
||||
}
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
return sb.toString();
|
||||
.writeCookieValue(new CookieValue(request, response, sessionId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInvalidateSession(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
Map<String, String> sessionIds = getSessionIds(request);
|
||||
String requestedAlias = getCurrentSessionAlias(request);
|
||||
sessionIds.remove(requestedAlias);
|
||||
|
||||
String cookieValue = createSessionCookieValue(sessionIds);
|
||||
this.cookieSerializer
|
||||
.writeCookieValue(new CookieValue(request, response, cookieValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the HTTP parameter that is used to specify the session alias. If
|
||||
* the value is null, then only a single session is supported per browser.
|
||||
*
|
||||
* @param sessionAliasParamName the name of the HTTP parameter used to specify the
|
||||
* session alias. If null, then ony a single session is supported per browser.
|
||||
*/
|
||||
public void setSessionAliasParamName(String sessionAliasParamName) {
|
||||
this.sessionParam = sessionAliasParamName;
|
||||
this.cookieSerializer.writeCookieValue(new CookieValue(request, response, ""));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -298,151 +104,4 @@ public final class CookieHttpSessionStrategy
|
||||
this.cookieSerializer = cookieSerializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<>();
|
||||
StringTokenizer tokens = new StringTokenizer(sessionCookieValue,
|
||||
this.deserializationDelimiter);
|
||||
if (tokens.countTokens() == 1) {
|
||||
result.put(DEFAULT_ALIAS, tokens.nextToken());
|
||||
return result;
|
||||
}
|
||||
while (tokens.hasMoreTokens()) {
|
||||
String alias = tokens.nextToken();
|
||||
if (!tokens.hasMoreTokens()) {
|
||||
break;
|
||||
}
|
||||
String id = tokens.nextToken();
|
||||
result.put(alias, id);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public HttpServletRequest wrapRequest(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
request.setAttribute(HttpSessionManager.class.getName(), this);
|
||||
return request;
|
||||
}
|
||||
|
||||
public HttpServletResponse wrapResponse(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
return new MultiSessionHttpServletResponse(response, request);
|
||||
}
|
||||
|
||||
public String encodeURL(String url, String sessionAlias) {
|
||||
String encodedSessionAlias = urlEncode(sessionAlias);
|
||||
int queryStart = url.indexOf("?");
|
||||
boolean isDefaultAlias = DEFAULT_ALIAS.equals(encodedSessionAlias);
|
||||
if (queryStart < 0) {
|
||||
return isDefaultAlias ? url
|
||||
: url + "?" + this.sessionParam + "=" + encodedSessionAlias;
|
||||
}
|
||||
String path = url.substring(0, queryStart);
|
||||
String query = url.substring(queryStart + 1, url.length());
|
||||
String replacement = isDefaultAlias ? "" : "$1" + encodedSessionAlias;
|
||||
query = query.replaceFirst("((^|&)" + this.sessionParam + "=)([^&]+)?",
|
||||
replacement);
|
||||
String sessionParamReplacement = String.format("%s=%s", this.sessionParam,
|
||||
encodedSessionAlias);
|
||||
|
||||
if (!isDefaultAlias && !query.contains(sessionParamReplacement)
|
||||
&& url.endsWith(query)) {
|
||||
// no existing alias
|
||||
if (!(query.endsWith("&") || query.length() == 0)) {
|
||||
query += "&";
|
||||
}
|
||||
query += sessionParamReplacement;
|
||||
}
|
||||
|
||||
return path + "?" + query;
|
||||
}
|
||||
|
||||
private String urlEncode(String value) {
|
||||
try {
|
||||
return URLEncoder.encode(value, "UTF-8");
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link CookieHttpSessionStrategy} aware {@link HttpServletResponseWrapper}.
|
||||
*/
|
||||
class MultiSessionHttpServletResponse extends HttpServletResponseWrapper {
|
||||
private final HttpServletRequest request;
|
||||
|
||||
MultiSessionHttpServletResponse(HttpServletResponse response,
|
||||
HttpServletRequest request) {
|
||||
super(response);
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
private String getCurrentSessionAliasFromUrl(String url) {
|
||||
String currentSessionAliasFromUrl = null;
|
||||
int queryStart = url.indexOf("?");
|
||||
|
||||
if (queryStart >= 0) {
|
||||
String query = url.substring(queryStart + 1);
|
||||
Matcher matcher = Pattern
|
||||
.compile(String.format("%s=([^&]+)",
|
||||
CookieHttpSessionStrategy.this.sessionParam))
|
||||
.matcher(query);
|
||||
|
||||
if (matcher.find()) {
|
||||
currentSessionAliasFromUrl = matcher.group(1);
|
||||
}
|
||||
}
|
||||
|
||||
return currentSessionAliasFromUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeRedirectURL(String url) {
|
||||
String encodedUrl = super.encodeRedirectURL(url);
|
||||
String currentSessionAliasFromUrl = getCurrentSessionAliasFromUrl(encodedUrl);
|
||||
String alias = (currentSessionAliasFromUrl != null)
|
||||
? currentSessionAliasFromUrl : getCurrentSessionAlias(this.request);
|
||||
|
||||
return CookieHttpSessionStrategy.this.encodeURL(encodedUrl, alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeURL(String url) {
|
||||
String encodedUrl = super.encodeURL(url);
|
||||
String currentSessionAliasFromUrl = getCurrentSessionAliasFromUrl(encodedUrl);
|
||||
String alias = (currentSessionAliasFromUrl != null)
|
||||
? currentSessionAliasFromUrl : getCurrentSessionAlias(this.request);
|
||||
|
||||
return CookieHttpSessionStrategy.this.encodeURL(encodedUrl, alias);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.session.web.http;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -52,21 +55,27 @@ import org.springframework.session.Session;
|
||||
* </pre>
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Vedran Pavic
|
||||
* @since 1.0
|
||||
*/
|
||||
public class HeaderHttpSessionStrategy implements HttpSessionStrategy {
|
||||
|
||||
private String headerName = "X-Auth-Token";
|
||||
|
||||
public String getRequestedSessionId(HttpServletRequest request) {
|
||||
return request.getHeader(this.headerName);
|
||||
@Override
|
||||
public List<String> getRequestedSessionIds(HttpServletRequest request) {
|
||||
String headerValue = request.getHeader(this.headerName);
|
||||
return headerValue != null ? Collections.singletonList(headerValue)
|
||||
: Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewSession(Session session, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
response.setHeader(this.headerName, session.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInvalidateSession(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
response.setHeader(this.headerName, "");
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.session.web.http;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Allows managing a mapping of alias to the session id for having multiple active
|
||||
* sessions at the same time.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 1.0
|
||||
*
|
||||
*/
|
||||
public interface HttpSessionManager {
|
||||
|
||||
/**
|
||||
* Gets the current session's alias from the {@link HttpServletRequest}.
|
||||
*
|
||||
* @param request the {@link HttpServletRequest} to obtain the current session's alias
|
||||
* from.
|
||||
* @return the current sessions' alias. Cannot be null.
|
||||
*/
|
||||
String getCurrentSessionAlias(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* Gets a mapping of the session alias to the session id from the
|
||||
* {@link HttpServletRequest}.
|
||||
*
|
||||
* @param request the {@link HttpServletRequest} to obtain the mapping from. Cannot be
|
||||
* null.
|
||||
* @return a mapping of the session alias to the session id from the
|
||||
* {@link HttpServletRequest}. Cannot be null.
|
||||
*/
|
||||
Map<String, String> getSessionIds(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* Provides the ability to encode the URL for a given session alias.
|
||||
*
|
||||
* @param url the url to encode.
|
||||
* @param sessionAlias the session alias to encode.
|
||||
* @return the encoded URL
|
||||
*/
|
||||
String encodeURL(String url, String sessionAlias);
|
||||
|
||||
/**
|
||||
* Gets a new and unique Session alias. Typically this will be called to pass into
|
||||
* {@code HttpSessionManager#encodeURL(java.lang.String)}. For example:
|
||||
*
|
||||
* <code>
|
||||
* String newAlias = httpSessionManager.getNewSessionAlias(request);
|
||||
* String addAccountUrl = httpSessionManager.encodeURL("./", newAlias);
|
||||
* </code>
|
||||
*
|
||||
* @param request the {@link HttpServletRequest} to get a new alias from
|
||||
* @return Gets a new and unique Session alias.
|
||||
*/
|
||||
String getNewSessionAlias(HttpServletRequest request);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.session.web.http;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -25,6 +27,7 @@ import org.springframework.session.Session;
|
||||
* A strategy for mapping HTTP request and responses to a {@link Session}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Vedran Pavic
|
||||
* @since 1.0
|
||||
*/
|
||||
public interface HttpSessionStrategy {
|
||||
@@ -36,10 +39,9 @@ public interface HttpSessionStrategy {
|
||||
*
|
||||
* @param request the {@link javax.servlet.http.HttpServletRequest} to obtain the
|
||||
* session id from. Cannot be null.
|
||||
* @return the {@link javax.servlet.http.HttpServletRequest} to obtain the session id
|
||||
* from.
|
||||
* @return the session ids
|
||||
*/
|
||||
String getRequestedSessionId(HttpServletRequest request);
|
||||
List<String> getRequestedSessionIds(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* This method is invoked when a new session is created and should inform a client
|
||||
@@ -76,4 +78,5 @@ public interface HttpSessionStrategy {
|
||||
* the {@link org.springframework.session.Session} Cannot be null.
|
||||
*/
|
||||
void onInvalidateSession(HttpServletRequest request, HttpServletResponse response);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.session.web.http;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Some {@link HttpSessionStrategy} may also want to further customize
|
||||
* {@link HttpServletRequest} and {@link HttpServletResponse} objects. For example,
|
||||
* {@link CookieHttpSessionStrategy} customizes how URL rewriting is done to select which
|
||||
* session should be used in the event multiple sessions are active.
|
||||
* </p>
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 1.0
|
||||
* @see CookieHttpSessionStrategy
|
||||
*/
|
||||
public interface MultiHttpSessionStrategy
|
||||
extends HttpSessionStrategy, RequestResponsePostProcessor {
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.session.web.http;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Allows customizing the {@link HttpServletRequest} and/or the
|
||||
* {@link HttpServletResponse}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 1.0
|
||||
*/
|
||||
public interface RequestResponsePostProcessor {
|
||||
|
||||
/**
|
||||
* Allows customizing the {@link HttpServletRequest}.
|
||||
*
|
||||
* @param request the original {@link HttpServletRequest}. Cannot be null.
|
||||
* @param response the original {@link HttpServletResponse}. This is NOT the result of
|
||||
* {@link #wrapResponse(HttpServletRequest, HttpServletResponse)} Cannot be null. .
|
||||
* @return a non-null {@link HttpServletRequest}
|
||||
*/
|
||||
HttpServletRequest wrapRequest(HttpServletRequest request,
|
||||
HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* Allows customizing the {@link HttpServletResponse}.
|
||||
*
|
||||
* @param request the original {@link HttpServletRequest}. This is NOT the result of
|
||||
* {@link #wrapRequest(HttpServletRequest, HttpServletResponse)}. Cannot be null.
|
||||
* @param response the original {@link HttpServletResponse}. Cannot be null.
|
||||
* @return a non-null {@link HttpServletResponse}
|
||||
*/
|
||||
HttpServletResponse wrapResponse(HttpServletRequest request,
|
||||
HttpServletResponse response);
|
||||
}
|
||||
@@ -51,10 +51,10 @@ import org.springframework.session.SessionRepository;
|
||||
*
|
||||
* <ul>
|
||||
* <li>The session id is looked up using
|
||||
* {@link HttpSessionStrategy#getRequestedSessionId(javax.servlet.http.HttpServletRequest)}
|
||||
* {@link HttpSessionStrategy#getRequestedSessionIds(javax.servlet.http.HttpServletRequest)}
|
||||
* . The default is to look in a cookie named SESSION.</li>
|
||||
* <li>The session id of newly created {@link org.springframework.session.Session}
|
||||
* is sent to the client using
|
||||
* <li>The session id of newly created {@link org.springframework.session.Session} is sent
|
||||
* to the client using
|
||||
* <li>The client is notified that the session id is no longer valid with
|
||||
* {@link HttpSessionStrategy#onInvalidateSession(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
|
||||
* </li>
|
||||
@@ -69,10 +69,11 @@ import org.springframework.session.SessionRepository;
|
||||
* @param <S> the {@link Session} type.
|
||||
* @since 1.0
|
||||
* @author Rob Winch
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@Order(SessionRepositoryFilter.DEFAULT_ORDER)
|
||||
public class SessionRepositoryFilter<S extends Session>
|
||||
extends OncePerRequestFilter {
|
||||
public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFilter {
|
||||
|
||||
private static final String SESSION_LOGGER_NAME = SessionRepositoryFilter.class
|
||||
.getName().concat(".SESSION_LOGGER");
|
||||
|
||||
@@ -102,7 +103,7 @@ public class SessionRepositoryFilter<S extends Session>
|
||||
|
||||
private ServletContext servletContext;
|
||||
|
||||
private MultiHttpSessionStrategy httpSessionStrategy = new CookieHttpSessionStrategy();
|
||||
private HttpSessionStrategy httpSessionStrategy = new CookieHttpSessionStrategy();
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
@@ -123,21 +124,6 @@ public class SessionRepositoryFilter<S extends Session>
|
||||
* @param httpSessionStrategy the {@link HttpSessionStrategy} to use. Cannot be null.
|
||||
*/
|
||||
public void setHttpSessionStrategy(HttpSessionStrategy httpSessionStrategy) {
|
||||
if (httpSessionStrategy == null) {
|
||||
throw new IllegalArgumentException("httpSessionStrategy cannot be null");
|
||||
}
|
||||
this.httpSessionStrategy = new MultiHttpSessionStrategyAdapter(
|
||||
httpSessionStrategy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link MultiHttpSessionStrategy} to be used. The default is a
|
||||
* {@link CookieHttpSessionStrategy}.
|
||||
*
|
||||
* @param httpSessionStrategy the {@link MultiHttpSessionStrategy} to use. Cannot be
|
||||
* null.
|
||||
*/
|
||||
public void setHttpSessionStrategy(MultiHttpSessionStrategy httpSessionStrategy) {
|
||||
if (httpSessionStrategy == null) {
|
||||
throw new IllegalArgumentException("httpSessionStrategy cannot be null");
|
||||
}
|
||||
@@ -155,13 +141,8 @@ public class SessionRepositoryFilter<S extends Session>
|
||||
SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(
|
||||
wrappedRequest, response);
|
||||
|
||||
HttpServletRequest strategyRequest = this.httpSessionStrategy
|
||||
.wrapRequest(wrappedRequest, wrappedResponse);
|
||||
HttpServletResponse strategyResponse = this.httpSessionStrategy
|
||||
.wrapResponse(wrappedRequest, wrappedResponse);
|
||||
|
||||
try {
|
||||
filterChain.doFilter(strategyRequest, strategyResponse);
|
||||
filterChain.doFilter(wrappedRequest, wrappedResponse);
|
||||
}
|
||||
finally {
|
||||
wrappedRequest.commitSession();
|
||||
@@ -213,9 +194,13 @@ public class SessionRepositoryFilter<S extends Session>
|
||||
*/
|
||||
private final class SessionRepositoryRequestWrapper
|
||||
extends HttpServletRequestWrapper {
|
||||
|
||||
private Boolean requestedSessionIdValid;
|
||||
|
||||
private boolean requestedSessionInvalidated;
|
||||
|
||||
private final HttpServletResponse response;
|
||||
|
||||
private final ServletContext servletContext;
|
||||
|
||||
private SessionRepositoryRequestWrapper(HttpServletRequest request,
|
||||
@@ -262,6 +247,7 @@ public class SessionRepositoryFilter<S extends Session>
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unused")
|
||||
public String changeSessionId() {
|
||||
HttpSession session = getSession(false);
|
||||
@@ -313,25 +299,24 @@ public class SessionRepositoryFilter<S extends Session>
|
||||
return currentSession;
|
||||
}
|
||||
String requestedSessionId = getRequestedSessionId();
|
||||
if (requestedSessionId != null
|
||||
&& getAttribute(INVALID_SESSION_ID_ATTR) == null) {
|
||||
S session = getSession(requestedSessionId);
|
||||
if (session != null) {
|
||||
if (requestedSessionId != null) {
|
||||
if (getAttribute(INVALID_SESSION_ID_ATTR) == null) {
|
||||
S session = getSession(requestedSessionId);
|
||||
this.requestedSessionIdValid = true;
|
||||
currentSession = new HttpSessionWrapper(session, getServletContext());
|
||||
currentSession.setNew(false);
|
||||
setCurrentSession(currentSession);
|
||||
return currentSession;
|
||||
}
|
||||
else {
|
||||
// This is an invalid session id. No need to ask again if
|
||||
// request.getSession is invoked for the duration of this request
|
||||
if (SESSION_LOGGER.isDebugEnabled()) {
|
||||
SESSION_LOGGER.debug(
|
||||
"No session found by id: Caching result for getSession(false) for this HttpServletRequest.");
|
||||
}
|
||||
setAttribute(INVALID_SESSION_ID_ATTR, "true");
|
||||
}
|
||||
else {
|
||||
// This is an invalid session id. No need to ask again if
|
||||
// request.getSession is invoked for the duration of this request
|
||||
if (SESSION_LOGGER.isDebugEnabled()) {
|
||||
SESSION_LOGGER.debug(
|
||||
"No session found by id: Caching result for getSession(false) for this HttpServletRequest.");
|
||||
}
|
||||
setAttribute(INVALID_SESSION_ID_ATTR, "true");
|
||||
}
|
||||
if (!create) {
|
||||
return null;
|
||||
@@ -367,7 +352,10 @@ public class SessionRepositoryFilter<S extends Session>
|
||||
@Override
|
||||
public String getRequestedSessionId() {
|
||||
return SessionRepositoryFilter.this.httpSessionStrategy
|
||||
.getRequestedSessionId(this);
|
||||
.getRequestedSessionIds(this).stream()
|
||||
.filter(sessionId -> SessionRepositoryFilter.this.sessionRepository
|
||||
.findById(sessionId) != null)
|
||||
.findFirst().orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -390,44 +378,7 @@ public class SessionRepositoryFilter<S extends Session>
|
||||
SessionRepositoryFilter.this.sessionRepository.deleteById(getId());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A delegating implementation of {@link MultiHttpSessionStrategy}.
|
||||
*/
|
||||
static class MultiHttpSessionStrategyAdapter implements MultiHttpSessionStrategy {
|
||||
private HttpSessionStrategy delegate;
|
||||
|
||||
/**
|
||||
* Create a new {@link MultiHttpSessionStrategyAdapter} instance.
|
||||
* @param delegate the delegate HTTP session strategy
|
||||
*/
|
||||
MultiHttpSessionStrategyAdapter(HttpSessionStrategy delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public String getRequestedSessionId(HttpServletRequest request) {
|
||||
return this.delegate.getRequestedSessionId(request);
|
||||
}
|
||||
|
||||
public void onNewSession(Session session, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
this.delegate.onNewSession(session, request, response);
|
||||
}
|
||||
|
||||
public void onInvalidateSession(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
this.delegate.onInvalidateSession(request, response);
|
||||
}
|
||||
|
||||
public HttpServletRequest wrapRequest(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
return request;
|
||||
}
|
||||
|
||||
public HttpServletResponse wrapResponse(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
package org.springframework.session.config.annotation.web.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
@@ -35,8 +34,9 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.mock.web.MockFilterChain;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.session.MapSessionRepository;
|
||||
import org.springframework.session.MapSession;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.session.web.http.CookieSerializer;
|
||||
import org.springframework.session.web.http.CookieSerializer.CookieValue;
|
||||
import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
@@ -46,6 +46,7 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -72,6 +73,9 @@ public class EnableSpringHttpSessionCustomCookieSerializerTests {
|
||||
@Autowired
|
||||
private SessionRepositoryFilter<? extends Session> sessionRepositoryFilter;
|
||||
|
||||
@Autowired
|
||||
private SessionRepository sessionRepository;
|
||||
|
||||
@Autowired
|
||||
private CookieSerializer cookieSerializer;
|
||||
|
||||
@@ -84,7 +88,9 @@ public class EnableSpringHttpSessionCustomCookieSerializerTests {
|
||||
public void usesReadSessionIds() throws Exception {
|
||||
String sessionId = "sessionId";
|
||||
given(this.cookieSerializer.readCookieValues(any(HttpServletRequest.class)))
|
||||
.willReturn(Arrays.asList(sessionId));
|
||||
.willReturn(Collections.singletonList(sessionId));
|
||||
given(this.sessionRepository.findById(anyString()))
|
||||
.willReturn(new MapSession(sessionId));
|
||||
|
||||
this.sessionRepositoryFilter.doFilter(this.request, this.response, this.chain);
|
||||
|
||||
@@ -93,6 +99,8 @@ public class EnableSpringHttpSessionCustomCookieSerializerTests {
|
||||
|
||||
@Test
|
||||
public void usesWrite() throws Exception {
|
||||
given(this.sessionRepository.findById(anyString())).willReturn(new MapSession());
|
||||
|
||||
this.sessionRepositoryFilter.doFilter(this.request, this.response,
|
||||
new MockFilterChain() {
|
||||
|
||||
@@ -116,8 +124,8 @@ public class EnableSpringHttpSessionCustomCookieSerializerTests {
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public MapSessionRepository mapSessionRepository() {
|
||||
return new MapSessionRepository(new ConcurrentHashMap<>());
|
||||
public SessionRepository sessionRepository() {
|
||||
return mock(SessionRepository.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.session.config.annotation.web.http;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.mock.web.MockFilterChain;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.session.MapSessionRepository;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.web.http.MultiHttpSessionStrategy;
|
||||
import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link SpringHttpSessionConfiguration} using a custom
|
||||
* {@link MultiHttpSessionStrategy}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@WebAppConfiguration
|
||||
public class EnableSpringHttpSessionCustomMultiHttpSessionStrategyTests {
|
||||
|
||||
@Autowired
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
@Autowired
|
||||
private MockHttpServletResponse response;
|
||||
|
||||
private MockFilterChain chain;
|
||||
|
||||
@Autowired
|
||||
private SessionRepositoryFilter<? extends Session> sessionRepositoryFilter;
|
||||
|
||||
@Autowired
|
||||
private MultiHttpSessionStrategy strategy;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.chain = new MockFilterChain();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wrapRequestAndResponseUsed() throws Exception {
|
||||
given(this.strategy.wrapRequest(any(HttpServletRequest.class),
|
||||
any(HttpServletResponse.class))).willReturn(this.request);
|
||||
given(this.strategy.wrapResponse(any(HttpServletRequest.class),
|
||||
any(HttpServletResponse.class))).willReturn(this.response);
|
||||
|
||||
this.sessionRepositoryFilter.doFilter(this.request, this.response, this.chain);
|
||||
|
||||
verify(this.strategy).wrapRequest(any(HttpServletRequest.class),
|
||||
any(HttpServletResponse.class));
|
||||
verify(this.strategy).wrapResponse(any(HttpServletRequest.class),
|
||||
any(HttpServletResponse.class));
|
||||
}
|
||||
|
||||
@EnableSpringHttpSession
|
||||
@Configuration
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public MapSessionRepository mapSessionRepository() {
|
||||
return new MapSessionRepository(new ConcurrentHashMap<>());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MultiHttpSessionStrategy strategy() {
|
||||
return mock(MultiHttpSessionStrategy.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,10 +17,9 @@
|
||||
package org.springframework.session.web.http;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.Map;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -32,7 +31,11 @@ import org.springframework.session.Session;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link CookieHttpSessionStrategy}.
|
||||
*/
|
||||
public class CookieHttpSessionStrategyTests {
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
private MockHttpServletResponse response;
|
||||
|
||||
@@ -51,22 +54,22 @@ public class CookieHttpSessionStrategyTests {
|
||||
|
||||
@Test
|
||||
public void getRequestedSessionIdNull() throws Exception {
|
||||
assertThat(this.strategy.getRequestedSessionId(this.request)).isNull();
|
||||
assertThat(this.strategy.getRequestedSessionIds(this.request)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestedSessionIdNotNull() throws Exception {
|
||||
setSessionCookie(this.session.getId());
|
||||
assertThat(this.strategy.getRequestedSessionId(this.request))
|
||||
.isEqualTo(this.session.getId());
|
||||
assertThat(this.strategy.getRequestedSessionIds(this.request))
|
||||
.isEqualTo(Collections.singletonList(this.session.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestedSessionIdNotNullCustomCookieName() throws Exception {
|
||||
setCookieName("CUSTOM");
|
||||
setSessionCookie(this.session.getId());
|
||||
assertThat(this.strategy.getRequestedSessionId(this.request))
|
||||
.isEqualTo(this.session.getId());
|
||||
assertThat(this.strategy.getRequestedSessionIds(this.request))
|
||||
.isEqualTo(Collections.singletonList(this.session.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -97,46 +100,6 @@ public class CookieHttpSessionStrategyTests {
|
||||
assertThat(base64Decode(cookies[1].getValue())).isEqualTo(newSession.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onNewSessionExistingSessionSameAlias() throws Exception {
|
||||
Session existing = new MapSession();
|
||||
setSessionCookie(existing.getId());
|
||||
this.strategy.onNewSession(this.session, this.request, this.response);
|
||||
assertThat(getSessionId()).isEqualTo(this.session.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onNewSessionExistingSessionNewAlias() throws Exception {
|
||||
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 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 {
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, "new");
|
||||
this.strategy.onNewSession(this.session, this.request, this.response);
|
||||
assertThat(getSessionId()).isEqualTo("new " + this.session.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onNewSessionCookiePath() throws Exception {
|
||||
this.request.setContextPath("/somethingunique");
|
||||
@@ -177,533 +140,12 @@ public class CookieHttpSessionStrategyTests {
|
||||
assertThat(getSessionId()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeleteSessionExistingSessionSameAlias() throws Exception {
|
||||
Session existing = new MapSession();
|
||||
setSessionCookie("0 " + existing.getId() + " new " + this.session.getId());
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, "new");
|
||||
this.strategy.onInvalidateSession(this.request, this.response);
|
||||
assertThat(getSessionId()).isEqualTo(existing.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeleteSessionExistingSessionNewAlias() throws Exception {
|
||||
Session existing = new MapSession();
|
||||
setSessionCookie("0 " + existing.getId() + " new " + this.session.getId());
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, "new");
|
||||
this.strategy.onInvalidateSession(this.request, this.response);
|
||||
assertThat(getSessionId()).isEqualTo(existing.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLNoExistingQuery() {
|
||||
assertThat(this.strategy.encodeURL("/url", "2")).isEqualTo("/url?_s=2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLNoExistingQueryEmpty() {
|
||||
assertThat(this.strategy.encodeURL("/url?", "2")).isEqualTo("/url?_s=2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLExistingQueryNoAlias() {
|
||||
assertThat(this.strategy.encodeURL("/url?a=b", "2")).isEqualTo("/url?a=b&_s=2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLExistingQueryExistingAliasStart() {
|
||||
assertThat(this.strategy.encodeURL("/url?_s=1&y=z", "2"))
|
||||
.isEqualTo("/url?_s=2&y=z");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLExistingQueryExistingAliasMiddle() {
|
||||
assertThat(this.strategy.encodeURL("/url?a=b&_s=1&y=z", "2"))
|
||||
.isEqualTo("/url?a=b&_s=2&y=z");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLExistingQueryExistingAliasEnd() {
|
||||
assertThat(this.strategy.encodeURL("/url?a=b&_s=1", "2"))
|
||||
.isEqualTo("/url?a=b&_s=2");
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Test
|
||||
public void encodeURLExistingQueryParamEndsWithActualParamStart() {
|
||||
assertThat(this.strategy.encodeURL("/url?x_s=1&y=z", "2"))
|
||||
.isEqualTo("/url?x_s=1&y=z&_s=2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLExistingQueryParamEndsWithActualParamMiddle() {
|
||||
assertThat(this.strategy.encodeURL("/url?a=b&x_s=1&y=z", "2"))
|
||||
.isEqualTo("/url?a=b&x_s=1&y=z&_s=2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLExistingQueryParamEndsWithActualParamEnd() {
|
||||
assertThat(this.strategy.encodeURL("/url?a=b&x_s=1", "2"))
|
||||
.isEqualTo("/url?a=b&x_s=1&_s=2");
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Test
|
||||
public void encodeURLNoExistingQueryDefaultAlias() {
|
||||
assertThat(this.strategy.encodeURL("/url", "0")).isEqualTo("/url");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLNoExistingQueryEmptyDefaultAlias() {
|
||||
assertThat(this.strategy.encodeURL("/url?", "0")).isEqualTo("/url?");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLExistingQueryNoAliasDefaultAlias() {
|
||||
assertThat(this.strategy.encodeURL("/url?a=b", "0")).isEqualTo("/url?a=b");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLExistingQueryExistingAliasStartDefaultAlias() {
|
||||
// relaxed constraint as result /url?&y=z does not hurt anything (ideally should
|
||||
// remove the &)
|
||||
assertThat(this.strategy.encodeURL("/url?_s=1&y=z", "0"))
|
||||
.doesNotContain("_s=0&_s=1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLExistingQueryExistingAliasMiddleDefaultAlias() {
|
||||
assertThat(this.strategy.encodeURL("/url?a=b&_s=1&y=z", "0"))
|
||||
.isEqualTo("/url?a=b&y=z");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLExistingQueryExistingAliasEndDefaultAlias() {
|
||||
assertThat(this.strategy.encodeURL("/url?a=b&_s=1", "0")).isEqualTo("/url?a=b");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLWithSameAlias() {
|
||||
String url = String.format("/url?%s=1",
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME);
|
||||
assertThat(this.strategy.encodeURL(url, "1")).isEqualTo(url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLWithSameAliasOtherQueryParamsBefore() {
|
||||
String url = String.format("/url?a=b&%s=1",
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME);
|
||||
assertThat(this.strategy.encodeURL(url, "1")).isEqualTo(url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLWithSameAliasOtherQueryParamsAfter() {
|
||||
String url = String.format("/url?%s=1&a=b",
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME);
|
||||
assertThat(this.strategy.encodeURL(url, "1")).isEqualTo(url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLWithSameAliasOtherQueryParamsBeforeAndAfter() {
|
||||
String url = String.format("/url?a=b&%s=1&c=d",
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME);
|
||||
assertThat(this.strategy.encodeURL(url, "1")).isEqualTo(url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeURLMaliciousAlias() {
|
||||
assertThat(this.strategy.encodeURL("/url?a=b&_s=1",
|
||||
"\"> <script>alert('hi')</script>")).isEqualTo(
|
||||
"/url?a=b&_s=%22%3E+%3Cscript%3Ealert%28%27hi%27%29%3C%2Fscript%3E");
|
||||
}
|
||||
|
||||
// --- getCurrentSessionAlias
|
||||
|
||||
@Test
|
||||
public void getCurrentSessionAliasNull() {
|
||||
assertThat(this.strategy.getCurrentSessionAlias(this.request))
|
||||
.isEqualTo(CookieHttpSessionStrategy.DEFAULT_ALIAS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCurrentSessionAliasNullParamName() {
|
||||
this.strategy.setSessionAliasParamName(null);
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, "NOT USED");
|
||||
|
||||
assertThat(this.strategy.getCurrentSessionAlias(this.request))
|
||||
.isEqualTo(CookieHttpSessionStrategy.DEFAULT_ALIAS);
|
||||
}
|
||||
|
||||
// protect against malicious users
|
||||
@Test
|
||||
public void getCurrentSessionAliasContainsQuote() {
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, "here\"this");
|
||||
|
||||
assertThat(this.strategy.getCurrentSessionAlias(this.request))
|
||||
.isEqualTo(CookieHttpSessionStrategy.DEFAULT_ALIAS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCurrentSessionAliasContainsSingleQuote() {
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, "here'this");
|
||||
|
||||
assertThat(this.strategy.getCurrentSessionAlias(this.request))
|
||||
.isEqualTo(CookieHttpSessionStrategy.DEFAULT_ALIAS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCurrentSessionAliasContainsSpace() {
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, "here this");
|
||||
|
||||
assertThat(this.strategy.getCurrentSessionAlias(this.request))
|
||||
.isEqualTo(CookieHttpSessionStrategy.DEFAULT_ALIAS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCurrentSessionAliasContainsLt() {
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, "here<this");
|
||||
|
||||
assertThat(this.strategy.getCurrentSessionAlias(this.request))
|
||||
.isEqualTo(CookieHttpSessionStrategy.DEFAULT_ALIAS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCurrentSessionAliasContainsGt() {
|
||||
this.strategy.setSessionAliasParamName(null);
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, "here>this");
|
||||
|
||||
assertThat(this.strategy.getCurrentSessionAlias(this.request))
|
||||
.isEqualTo(CookieHttpSessionStrategy.DEFAULT_ALIAS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCurrentSessionAliasTooLong() {
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME,
|
||||
"012345678901234567890123456789012345678901234567890");
|
||||
|
||||
assertThat(this.strategy.getCurrentSessionAlias(this.request))
|
||||
.isEqualTo(CookieHttpSessionStrategy.DEFAULT_ALIAS);
|
||||
}
|
||||
|
||||
// We want some sort of length restrictions, but want to ensure some sort of length
|
||||
// Technically no hard limit, but chose 50
|
||||
@Test
|
||||
public void getCurrentSessionAliasAllows50() {
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME,
|
||||
"01234567890123456789012345678901234567890123456789");
|
||||
|
||||
assertThat(this.strategy.getCurrentSessionAlias(this.request))
|
||||
.isEqualTo("01234567890123456789012345678901234567890123456789");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCurrentSession() {
|
||||
String expectedAlias = "1";
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME,
|
||||
expectedAlias);
|
||||
assertThat(this.strategy.getCurrentSessionAlias(this.request))
|
||||
.isEqualTo(expectedAlias);
|
||||
}
|
||||
|
||||
// --- getNewSessionAlias
|
||||
|
||||
@Test
|
||||
public void getNewSessionAliasNoSessions() {
|
||||
assertThat(this.strategy.getNewSessionAlias(this.request))
|
||||
.isEqualTo(CookieHttpSessionStrategy.DEFAULT_ALIAS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNewSessionAliasSingleSession() {
|
||||
setSessionCookie("abc");
|
||||
|
||||
assertThat(this.strategy.getNewSessionAlias(this.request)).isEqualTo("1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNewSessionAlias2Sessions() {
|
||||
setCookieWithNSessions(2);
|
||||
|
||||
assertThat(this.strategy.getNewSessionAlias(this.request)).isEqualTo("2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNewSessionAlias9Sessions() {
|
||||
setCookieWithNSessions(9);
|
||||
|
||||
assertThat(this.strategy.getNewSessionAlias(this.request))
|
||||
.isEqualToIgnoringCase("9");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNewSessionAlias10Sessions() {
|
||||
setCookieWithNSessions(10);
|
||||
|
||||
assertThat(this.strategy.getNewSessionAlias(this.request))
|
||||
.isEqualToIgnoringCase("a");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNewSessionAlias16Sessions() {
|
||||
setCookieWithNSessions(16);
|
||||
|
||||
assertThat(this.strategy.getNewSessionAlias(this.request))
|
||||
.isEqualToIgnoringCase("10");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNewSessionAliasInvalidAlias() {
|
||||
setSessionCookie("0 1 $ b");
|
||||
|
||||
assertThat(this.strategy.getNewSessionAlias(this.request))
|
||||
.isEqualToIgnoringCase("1");
|
||||
}
|
||||
|
||||
// --- getSessionIds
|
||||
|
||||
@Test
|
||||
public void getSessionIdsNone() {
|
||||
assertThat(this.strategy.getSessionIds(this.request)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSessionIdsSingle() {
|
||||
String expectedId = "a";
|
||||
setSessionCookie(expectedId);
|
||||
|
||||
Map<String, String> sessionIds = this.strategy.getSessionIds(this.request);
|
||||
assertThat(sessionIds.size()).isEqualTo(1);
|
||||
assertThat(sessionIds.get("0")).isEqualTo(expectedId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSessionIdsMulti() {
|
||||
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 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");
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
// --- helper
|
||||
|
||||
@Test
|
||||
public void createSessionCookieValue() {
|
||||
assertThat(createSessionCookieValue(17)).isEqualToIgnoringCase(
|
||||
"0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 a 10 b 11 c 12 d 13 e 14 f 15 10 16");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseEncodeRedirectUrlWhereRedirectUrlDoesntContainAliasCurrentReqNoAlias() {
|
||||
String url = "http://www.somehost.com/some/path";
|
||||
HttpServletResponse wrappedResponse = this.strategy.wrapResponse(this.request,
|
||||
this.response);
|
||||
String encodedRedirectUrl = wrappedResponse.encodeRedirectURL(url);
|
||||
assertThat(encodedRedirectUrl).isEqualTo(url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseEncodeRedirectUrlWhereRedirectUrlDoesntContainAliasCurrentReqHasAlias() {
|
||||
String url = "http://www.somehost.com/some/path";
|
||||
String alias = "1";
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, alias);
|
||||
HttpServletResponse wrappedResponse = this.strategy.wrapResponse(this.request,
|
||||
this.response);
|
||||
String encodedRedirectUrl = wrappedResponse.encodeRedirectURL(url);
|
||||
assertThat(encodedRedirectUrl).isEqualTo(String.format("%s?%s=%s", url,
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, alias));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseEncodeRedirectUrlWhereRedirectUrlContainsAliasCurrentReqHasNoAlias() {
|
||||
String url = String.format("http://www.somehost.com/some/path?%s=5",
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME);
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, "4");
|
||||
HttpServletResponse wrappedResponse = this.strategy.wrapResponse(this.request,
|
||||
this.response);
|
||||
String encodedRedirectUrl = wrappedResponse.encodeRedirectURL(url);
|
||||
assertThat(encodedRedirectUrl).isEqualTo(url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseEncodeRedirectUrlWhereRedirectUrlDoesntContainAliasCurrentReqNoAliasWithOtherParams() {
|
||||
String url = "http://www.somehost.com/some/path?a=b";
|
||||
HttpServletResponse wrappedResponse = this.strategy.wrapResponse(this.request,
|
||||
this.response);
|
||||
String encodedRedirectUrl = wrappedResponse.encodeRedirectURL(url);
|
||||
assertThat(encodedRedirectUrl).isEqualTo(url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseEncodeRedirectUrlWhereRedirectUrlDoesntContainAliasCurrentReqHasAliasWithOtherParams() {
|
||||
String url = "http://www.somehost.com/some/path?a=b";
|
||||
String alias = "1";
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, alias);
|
||||
HttpServletResponse wrappedResponse = this.strategy.wrapResponse(this.request,
|
||||
this.response);
|
||||
String encodedRedirectUrl = wrappedResponse.encodeRedirectURL(url);
|
||||
assertThat(encodedRedirectUrl).isEqualTo(String.format("%s&%s=%s", url,
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, alias));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseEncodeRedirectUrlWhereRedirectUrlContainsAliasCurrentReqHasNoAliasWithOtherParams() {
|
||||
String url = String.format("http://www.somehost.com/some/path?a=b&%s=5&c=d",
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME);
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, "4");
|
||||
HttpServletResponse wrappedResponse = this.strategy.wrapResponse(this.request,
|
||||
this.response);
|
||||
String encodedRedirectUrl = wrappedResponse.encodeRedirectURL(url);
|
||||
assertThat(encodedRedirectUrl).isEqualTo(url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseEncodeUrlWhereRedirectUrlDoesntContainAliasCurrentReqNoAlias() {
|
||||
String url = "http://www.somehost.com/some/path";
|
||||
HttpServletResponse wrappedResponse = this.strategy.wrapResponse(this.request,
|
||||
this.response);
|
||||
String encodedUrl = wrappedResponse.encodeRedirectURL(url);
|
||||
assertThat(encodedUrl).isEqualTo(url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseEncodeUrlWhereRedirectUrlDoesntContainAliasCurrentReqHasAlias() {
|
||||
String url = "http://www.somehost.com/some/path";
|
||||
String alias = "1";
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, alias);
|
||||
HttpServletResponse wrappedResponse = this.strategy.wrapResponse(this.request,
|
||||
this.response);
|
||||
String encodedUrl = wrappedResponse.encodeRedirectURL(url);
|
||||
assertThat(encodedUrl).isEqualTo(String.format("%s?%s=%s", url,
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, alias));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseEncodeUrlWhereRedirectUrlContainsAliasCurrentReqHasNoAlias() {
|
||||
String url = String.format("http://www.somehost.com/some/path?%s=5",
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME);
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, "4");
|
||||
HttpServletResponse wrappedResponse = this.strategy.wrapResponse(this.request,
|
||||
this.response);
|
||||
String encodedUrl = wrappedResponse.encodeRedirectURL(url);
|
||||
assertThat(encodedUrl).isEqualTo(url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseEncodeUrlWhereRedirectUrlDoesntContainAliasCurrentReqNoAliasWithOtherParams() {
|
||||
String url = "http://www.somehost.com/some/path?a=b";
|
||||
HttpServletResponse wrappedResponse = this.strategy.wrapResponse(this.request,
|
||||
this.response);
|
||||
String encodedUrl = wrappedResponse.encodeRedirectURL(url);
|
||||
assertThat(encodedUrl).isEqualTo(url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseEncodeUrlWhereRedirectUrlDoesntContainAliasCurrentReqHasAliasWithOtherParams() {
|
||||
String url = "http://www.somehost.com/some/path?a=b";
|
||||
String alias = "1";
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, alias);
|
||||
HttpServletResponse wrappedResponse = this.strategy.wrapResponse(this.request,
|
||||
this.response);
|
||||
String encodedUrl = wrappedResponse.encodeRedirectURL(url);
|
||||
assertThat(encodedUrl).isEqualTo(String.format("%s&%s=%s", url,
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, alias));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseEncodeUrlWhereRedirectUrlContainsAliasCurrentReqHasNoAliasWithOtherParams() {
|
||||
String url = String.format("http://www.somehost.com/some/path?a=b&%s=5&c=d",
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME);
|
||||
this.request.setParameter(
|
||||
CookieHttpSessionStrategy.DEFAULT_SESSION_ALIAS_PARAM_NAME, "4");
|
||||
HttpServletResponse wrappedResponse = this.strategy.wrapResponse(this.request,
|
||||
this.response);
|
||||
String encodedUrl = wrappedResponse.encodeRedirectURL(url);
|
||||
assertThat(encodedUrl).isEqualTo(url);
|
||||
}
|
||||
|
||||
private void setCookieWithNSessions(long size) {
|
||||
setSessionCookie(createSessionCookieValue(size));
|
||||
}
|
||||
|
||||
private String createSessionCookieValue(long size) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -720,18 +162,18 @@ public class CookieHttpSessionStrategyTests {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void setCookieName(String cookieName) {
|
||||
private void setCookieName(String cookieName) {
|
||||
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
|
||||
cookieSerializer.setCookieName(cookieName);
|
||||
this.strategy.setCookieSerializer(cookieSerializer);
|
||||
this.cookieName = cookieName;
|
||||
}
|
||||
|
||||
public void setSessionCookie(String value) {
|
||||
private void setSessionCookie(String value) {
|
||||
this.request.setCookies(new Cookie(this.cookieName, base64Encode(value)));
|
||||
}
|
||||
|
||||
public String getSessionId() {
|
||||
private String getSessionId() {
|
||||
return base64Decode(this.response.getCookie(this.cookieName).getValue());
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.session.web.http;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -26,6 +28,9 @@ import org.springframework.session.Session;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link HeaderHttpSessionStrategy}.
|
||||
*/
|
||||
public class HeaderSessionStrategyTests {
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
@@ -46,22 +51,22 @@ public class HeaderSessionStrategyTests {
|
||||
|
||||
@Test
|
||||
public void getRequestedSessionIdNull() throws Exception {
|
||||
assertThat(this.strategy.getRequestedSessionId(this.request)).isNull();
|
||||
assertThat(this.strategy.getRequestedSessionIds(this.request)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestedSessionIdNotNull() throws Exception {
|
||||
setSessionId(this.session.getId());
|
||||
assertThat(this.strategy.getRequestedSessionId(this.request))
|
||||
.isEqualTo(this.session.getId());
|
||||
assertThat(this.strategy.getRequestedSessionIds(this.request))
|
||||
.isEqualTo(Collections.singletonList(this.session.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestedSessionIdNotNullCustomHeaderName() throws Exception {
|
||||
setHeaderName("CUSTOM");
|
||||
setSessionId(this.session.getId());
|
||||
assertThat(this.strategy.getRequestedSessionId(this.request))
|
||||
.isEqualTo(this.session.getId());
|
||||
assertThat(this.strategy.getRequestedSessionIds(this.request))
|
||||
.isEqualTo(Collections.singletonList(this.session.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -116,16 +121,16 @@ public class HeaderSessionStrategyTests {
|
||||
this.strategy.setHeaderName(null);
|
||||
}
|
||||
|
||||
public void setHeaderName(String headerName) {
|
||||
private void setHeaderName(String headerName) {
|
||||
this.strategy.setHeaderName(headerName);
|
||||
this.headerName = headerName;
|
||||
}
|
||||
|
||||
public void setSessionId(String id) {
|
||||
private void setSessionId(String id) {
|
||||
this.request.addHeader(this.headerName, id);
|
||||
}
|
||||
|
||||
public String getSessionId() {
|
||||
private String getSessionId() {
|
||||
return this.response.getHeader(this.headerName);
|
||||
}
|
||||
|
||||
|
||||
@@ -60,12 +60,12 @@ import org.springframework.test.util.ReflectionTestUtils;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
|
||||
@@ -95,8 +95,7 @@ public class SessionRepositoryFilterTests {
|
||||
public void setup() throws Exception {
|
||||
this.sessions = new HashMap<>();
|
||||
this.sessionRepository = new MapSessionRepository(this.sessions);
|
||||
this.filter = new SessionRepositoryFilter<>(
|
||||
this.sessionRepository);
|
||||
this.filter = new SessionRepositoryFilter<>(this.sessionRepository);
|
||||
setupRequest();
|
||||
}
|
||||
|
||||
@@ -134,8 +133,7 @@ public class SessionRepositoryFilterTests {
|
||||
session.setLastAccessedTime(Instant.EPOCH);
|
||||
this.sessionRepository = spy(this.sessionRepository);
|
||||
given(this.sessionRepository.createSession()).willReturn(session);
|
||||
this.filter = new SessionRepositoryFilter<>(
|
||||
this.sessionRepository);
|
||||
this.filter = new SessionRepositoryFilter<>(this.sessionRepository);
|
||||
|
||||
doFilter(new DoInFilter() {
|
||||
@Override
|
||||
@@ -240,8 +238,7 @@ public class SessionRepositoryFilterTests {
|
||||
@Test
|
||||
public void doFilterServletContextExplicit() throws Exception {
|
||||
final ServletContext expectedContext = new MockServletContext();
|
||||
this.filter = new SessionRepositoryFilter<>(
|
||||
this.sessionRepository);
|
||||
this.filter = new SessionRepositoryFilter<>(this.sessionRepository);
|
||||
this.filter.setServletContext(expectedContext);
|
||||
|
||||
doFilter(new DoInFilter() {
|
||||
@@ -431,8 +428,7 @@ public class SessionRepositoryFilterTests {
|
||||
return createSession();
|
||||
}
|
||||
};
|
||||
this.filter = new SessionRepositoryFilter<>(
|
||||
this.sessionRepository);
|
||||
this.filter = new SessionRepositoryFilter<>(this.sessionRepository);
|
||||
doFilter(new DoInFilter() {
|
||||
@Override
|
||||
public void doFilter(HttpServletRequest wrappedRequest) {
|
||||
@@ -568,7 +564,7 @@ public class SessionRepositoryFilterTests {
|
||||
ReflectionTestUtils.invokeMethod(wrappedRequest, "changeSessionId");
|
||||
fail("Exected Exception");
|
||||
}
|
||||
catch (IllegalStateException success) {
|
||||
catch (IllegalStateException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -674,7 +670,7 @@ public class SessionRepositoryFilterTests {
|
||||
sessionContext.getIds().nextElement();
|
||||
fail("Expected Exception");
|
||||
}
|
||||
catch (NoSuchElementException success) {
|
||||
catch (NoSuchElementException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -725,7 +721,7 @@ public class SessionRepositoryFilterTests {
|
||||
session.invalidate();
|
||||
fail("Expected Exception");
|
||||
}
|
||||
catch (IllegalStateException success) {
|
||||
catch (IllegalStateException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -742,7 +738,7 @@ public class SessionRepositoryFilterTests {
|
||||
session.getCreationTime();
|
||||
fail("Expected Exception");
|
||||
}
|
||||
catch (IllegalStateException success) {
|
||||
catch (IllegalStateException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -759,7 +755,7 @@ public class SessionRepositoryFilterTests {
|
||||
session.getAttribute("attr");
|
||||
fail("Expected Exception");
|
||||
}
|
||||
catch (IllegalStateException success) {
|
||||
catch (IllegalStateException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -776,7 +772,7 @@ public class SessionRepositoryFilterTests {
|
||||
session.getValue("attr");
|
||||
fail("Expected Exception");
|
||||
}
|
||||
catch (IllegalStateException success) {
|
||||
catch (IllegalStateException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -793,7 +789,7 @@ public class SessionRepositoryFilterTests {
|
||||
session.getAttributeNames();
|
||||
fail("Expected Exception");
|
||||
}
|
||||
catch (IllegalStateException success) {
|
||||
catch (IllegalStateException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -810,7 +806,7 @@ public class SessionRepositoryFilterTests {
|
||||
session.getValueNames();
|
||||
fail("Expected Exception");
|
||||
}
|
||||
catch (IllegalStateException success) {
|
||||
catch (IllegalStateException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -827,7 +823,7 @@ public class SessionRepositoryFilterTests {
|
||||
session.setAttribute("a", "b");
|
||||
fail("Expected Exception");
|
||||
}
|
||||
catch (IllegalStateException success) {
|
||||
catch (IllegalStateException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -844,7 +840,7 @@ public class SessionRepositoryFilterTests {
|
||||
session.putValue("a", "b");
|
||||
fail("Expected Exception");
|
||||
}
|
||||
catch (IllegalStateException success) {
|
||||
catch (IllegalStateException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -861,7 +857,7 @@ public class SessionRepositoryFilterTests {
|
||||
session.removeAttribute("name");
|
||||
fail("Expected Exception");
|
||||
}
|
||||
catch (IllegalStateException success) {
|
||||
catch (IllegalStateException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -878,7 +874,7 @@ public class SessionRepositoryFilterTests {
|
||||
session.removeValue("name");
|
||||
fail("Expected Exception");
|
||||
}
|
||||
catch (IllegalStateException success) {
|
||||
catch (IllegalStateException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -895,7 +891,7 @@ public class SessionRepositoryFilterTests {
|
||||
session.isNew();
|
||||
fail("Expected Exception");
|
||||
}
|
||||
catch (IllegalStateException success) {
|
||||
catch (IllegalStateException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -912,7 +908,7 @@ public class SessionRepositoryFilterTests {
|
||||
session.getLastAccessedTime();
|
||||
fail("Expected Exception");
|
||||
}
|
||||
catch (IllegalStateException success) {
|
||||
catch (IllegalStateException ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1055,8 +1051,9 @@ public class SessionRepositoryFilterTests {
|
||||
HttpServletResponse wrappedResponse) throws IOException {
|
||||
String id = wrappedRequest.getSession().getId();
|
||||
wrappedResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
assertThat(SessionRepositoryFilterTests.this.sessionRepository
|
||||
.findById(id)).isNotNull();
|
||||
assertThat(
|
||||
SessionRepositoryFilterTests.this.sessionRepository.findById(id))
|
||||
.isNotNull();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1070,8 +1067,9 @@ public class SessionRepositoryFilterTests {
|
||||
String id = wrappedRequest.getSession().getId();
|
||||
wrappedResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
|
||||
"Error");
|
||||
assertThat(SessionRepositoryFilterTests.this.sessionRepository
|
||||
.findById(id)).isNotNull();
|
||||
assertThat(
|
||||
SessionRepositoryFilterTests.this.sessionRepository.findById(id))
|
||||
.isNotNull();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1084,8 +1082,9 @@ public class SessionRepositoryFilterTests {
|
||||
HttpServletResponse wrappedResponse) throws IOException {
|
||||
String id = wrappedRequest.getSession().getId();
|
||||
wrappedResponse.sendRedirect("/");
|
||||
assertThat(SessionRepositoryFilterTests.this.sessionRepository
|
||||
.findById(id)).isNotNull();
|
||||
assertThat(
|
||||
SessionRepositoryFilterTests.this.sessionRepository.findById(id))
|
||||
.isNotNull();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1098,8 +1097,9 @@ public class SessionRepositoryFilterTests {
|
||||
HttpServletResponse wrappedResponse) throws IOException {
|
||||
String id = wrappedRequest.getSession().getId();
|
||||
wrappedResponse.flushBuffer();
|
||||
assertThat(SessionRepositoryFilterTests.this.sessionRepository
|
||||
.findById(id)).isNotNull();
|
||||
assertThat(
|
||||
SessionRepositoryFilterTests.this.sessionRepository.findById(id))
|
||||
.isNotNull();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1112,8 +1112,9 @@ public class SessionRepositoryFilterTests {
|
||||
HttpServletResponse wrappedResponse) throws IOException {
|
||||
String id = wrappedRequest.getSession().getId();
|
||||
wrappedResponse.getOutputStream().flush();
|
||||
assertThat(SessionRepositoryFilterTests.this.sessionRepository
|
||||
.findById(id)).isNotNull();
|
||||
assertThat(
|
||||
SessionRepositoryFilterTests.this.sessionRepository.findById(id))
|
||||
.isNotNull();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1126,8 +1127,9 @@ public class SessionRepositoryFilterTests {
|
||||
HttpServletResponse wrappedResponse) throws IOException {
|
||||
String id = wrappedRequest.getSession().getId();
|
||||
wrappedResponse.getOutputStream().close();
|
||||
assertThat(SessionRepositoryFilterTests.this.sessionRepository
|
||||
.findById(id)).isNotNull();
|
||||
assertThat(
|
||||
SessionRepositoryFilterTests.this.sessionRepository.findById(id))
|
||||
.isNotNull();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1140,8 +1142,9 @@ public class SessionRepositoryFilterTests {
|
||||
HttpServletResponse wrappedResponse) throws IOException {
|
||||
String id = wrappedRequest.getSession().getId();
|
||||
wrappedResponse.getWriter().flush();
|
||||
assertThat(SessionRepositoryFilterTests.this.sessionRepository
|
||||
.findById(id)).isNotNull();
|
||||
assertThat(
|
||||
SessionRepositoryFilterTests.this.sessionRepository.findById(id))
|
||||
.isNotNull();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1154,20 +1157,28 @@ public class SessionRepositoryFilterTests {
|
||||
HttpServletResponse wrappedResponse) throws IOException {
|
||||
String id = wrappedRequest.getSession().getId();
|
||||
wrappedResponse.getWriter().close();
|
||||
assertThat(SessionRepositoryFilterTests.this.sessionRepository
|
||||
.findById(id)).isNotNull();
|
||||
assertThat(
|
||||
SessionRepositoryFilterTests.this.sessionRepository.findById(id))
|
||||
.isNotNull();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// --- MultiHttpSessionStrategyAdapter
|
||||
// --- HttpSessionStrategy
|
||||
|
||||
@Test
|
||||
public void doFilterAdapterGetRequestedSessionId() throws Exception {
|
||||
SessionRepository<MapSession> sessionRepository = spy(
|
||||
new MapSessionRepository(new ConcurrentHashMap<>()));
|
||||
|
||||
this.filter = new SessionRepositoryFilter<>(sessionRepository);
|
||||
this.filter.setHttpSessionStrategy(this.strategy);
|
||||
final String expectedId = "MultiHttpSessionStrategyAdapter-requested-id";
|
||||
given(this.strategy.getRequestedSessionId(any(HttpServletRequest.class)))
|
||||
.willReturn(expectedId);
|
||||
final String expectedId = "HttpSessionStrategy-requested-id";
|
||||
|
||||
given(this.strategy.getRequestedSessionIds(any(HttpServletRequest.class)))
|
||||
.willReturn(Collections.singletonList(expectedId));
|
||||
given(sessionRepository.findById(anyString()))
|
||||
.willReturn(new MapSession(expectedId));
|
||||
|
||||
doFilter(new DoInFilter() {
|
||||
@Override
|
||||
@@ -1211,8 +1222,8 @@ public class SessionRepositoryFilterTests {
|
||||
|
||||
HttpServletRequest request = (HttpServletRequest) this.chain.getRequest();
|
||||
String id = request.getSession().getId();
|
||||
given(this.strategy.getRequestedSessionId(any(HttpServletRequest.class)))
|
||||
.willReturn(id);
|
||||
given(this.strategy.getRequestedSessionIds(any(HttpServletRequest.class)))
|
||||
.willReturn(Collections.singletonList(id));
|
||||
setupRequest();
|
||||
|
||||
doFilter(new DoInFilter() {
|
||||
@@ -1243,8 +1254,8 @@ public class SessionRepositoryFilterTests {
|
||||
|
||||
HttpServletRequest request = (HttpServletRequest) this.chain.getRequest();
|
||||
String id = request.getSession().getId();
|
||||
given(this.strategy.getRequestedSessionId(any(HttpServletRequest.class)))
|
||||
.willReturn(id);
|
||||
given(this.strategy.getRequestedSessionIds(any(HttpServletRequest.class)))
|
||||
.willReturn(Collections.singletonList(id));
|
||||
|
||||
doFilter(new DoInFilter() {
|
||||
@Override
|
||||
@@ -1340,52 +1351,7 @@ public class SessionRepositoryFilterTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void setHttpSessionStrategyNull() {
|
||||
this.filter.setHttpSessionStrategy((HttpSessionStrategy) null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void setMultiHttpSessionStrategyNull() {
|
||||
this.filter.setHttpSessionStrategy((MultiHttpSessionStrategy) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSessionFalseWithInvalidSessionIdShouldOnlyAskRepositoryOnce()
|
||||
throws ServletException, IOException {
|
||||
this.sessionRepository = spy(this.sessionRepository);
|
||||
this.filter = new SessionRepositoryFilter<>(
|
||||
this.sessionRepository);
|
||||
|
||||
final String nonExistantSessionId = "nonExistantSessionId";
|
||||
setSessionCookie(nonExistantSessionId);
|
||||
|
||||
doFilter(new DoInFilter() {
|
||||
@Override
|
||||
public void doFilter(HttpServletRequest wrappedRequest) {
|
||||
// Before first invocation
|
||||
assertThat(SessionRepositoryFilterTests.this.request
|
||||
.getAttribute(SessionRepositoryFilter.INVALID_SESSION_ID_ATTR))
|
||||
.isNull();
|
||||
|
||||
// First call should go all the way through to the sessioRepository (it
|
||||
// will not find the session)
|
||||
HttpSession session = wrappedRequest.getSession(false);
|
||||
verify(SessionRepositoryFilterTests.this.sessionRepository, times(1))
|
||||
.findById(nonExistantSessionId);
|
||||
assertThat(session).isNull();
|
||||
assertThat(SessionRepositoryFilterTests.this.request
|
||||
.getAttribute(SessionRepositoryFilter.INVALID_SESSION_ID_ATTR))
|
||||
.isNotNull();
|
||||
|
||||
// Second call should not reach the sessionRepository
|
||||
session = wrappedRequest.getSession(false);
|
||||
verify(SessionRepositoryFilterTests.this.sessionRepository, times(1))
|
||||
.findById(nonExistantSessionId); // still only called once
|
||||
assertThat(session).isNull();
|
||||
assertThat(SessionRepositoryFilterTests.this.request
|
||||
.getAttribute(SessionRepositoryFilter.INVALID_SESSION_ID_ATTR))
|
||||
.isNotNull();
|
||||
}
|
||||
});
|
||||
this.filter.setHttpSessionStrategy(null);
|
||||
}
|
||||
|
||||
// --- helper methods
|
||||
@@ -1435,10 +1401,8 @@ public class SessionRepositoryFilterTests {
|
||||
nameToCookie.put(cookie.getName(), cookie);
|
||||
}
|
||||
}
|
||||
if (this.response.getCookies() != null) {
|
||||
for (Cookie cookie : this.response.getCookies()) {
|
||||
nameToCookie.put(cookie.getName(), cookie);
|
||||
}
|
||||
for (Cookie cookie : this.response.getCookies()) {
|
||||
nameToCookie.put(cookie.getName(), cookie);
|
||||
}
|
||||
Cookie[] nextRequestCookies = new ArrayList<>(nameToCookie.values())
|
||||
.toArray(new Cookie[0]);
|
||||
@@ -1448,7 +1412,6 @@ public class SessionRepositoryFilterTests {
|
||||
this.request.setCookies(nextRequestCookies);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private void doFilter(final DoInFilter doInFilter)
|
||||
throws ServletException, IOException {
|
||||
this.chain = new MockFilterChain(new HttpServlet() {
|
||||
@@ -1456,7 +1419,7 @@ public class SessionRepositoryFilterTests {
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
throws ServletException, IOException {
|
||||
doInFilter.doFilter(request, response);
|
||||
}
|
||||
});
|
||||
@@ -1471,21 +1434,25 @@ public class SessionRepositoryFilterTests {
|
||||
return new String(Base64.getDecoder().decode(value));
|
||||
}
|
||||
|
||||
abstract class DoInFilter {
|
||||
private static class SessionRepositoryFilterDefaultOrder implements Ordered {
|
||||
|
||||
public int getOrder() {
|
||||
return SessionRepositoryFilter.DEFAULT_ORDER;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private abstract class DoInFilter {
|
||||
|
||||
void doFilter(HttpServletRequest wrappedRequest,
|
||||
HttpServletResponse wrappedResponse)
|
||||
throws ServletException, IOException {
|
||||
throws ServletException, IOException {
|
||||
doFilter(wrappedRequest);
|
||||
}
|
||||
|
||||
void doFilter(HttpServletRequest wrappedRequest) {
|
||||
}
|
||||
}
|
||||
|
||||
static class SessionRepositoryFilterDefaultOrder implements Ordered {
|
||||
public int getOrder() {
|
||||
return SessionRepositoryFilter.DEFAULT_ORDER;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user