@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -27,8 +27,7 @@ import java.util.Map;
|
||||
* @author Rob Winch
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
public interface FindByIndexNameSessionRepository<S extends Session>
|
||||
extends SessionRepository<S> {
|
||||
public interface FindByIndexNameSessionRepository<S extends Session> extends SessionRepository<S> {
|
||||
|
||||
/**
|
||||
* A session index that contains the current principal name (i.e. username).
|
||||
@@ -44,7 +43,6 @@ public interface FindByIndexNameSessionRepository<S extends Session>
|
||||
/**
|
||||
* Find a {@link Map} of the session id to the {@link Session} of all sessions that
|
||||
* contain the specified index name index value.
|
||||
*
|
||||
* @param indexName the name of the index (i.e.
|
||||
* {@link FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME})
|
||||
* @param indexValue the value of the index to search for.
|
||||
@@ -59,7 +57,6 @@ public interface FindByIndexNameSessionRepository<S extends Session>
|
||||
* contain the index with the name
|
||||
* {@link FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME} and the
|
||||
* specified principal name.
|
||||
*
|
||||
* @param principalName the principal name
|
||||
* @return a {@code Map} (never {@code null}) of the session id to the {@code Session}
|
||||
* of all sessions that contain the specified principal name. If no results are found,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -47,15 +47,20 @@ import java.util.UUID;
|
||||
* @since 1.0
|
||||
*/
|
||||
public final class MapSession implements Session, Serializable {
|
||||
|
||||
/**
|
||||
* Default {@link #setMaxInactiveInterval(Duration)} (30 minutes).
|
||||
*/
|
||||
public static final int DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS = 1800;
|
||||
|
||||
private String id;
|
||||
|
||||
private final String originalId;
|
||||
|
||||
private Map<String, Object> sessionAttrs = new HashMap<>();
|
||||
|
||||
private Instant creationTime = Instant.now();
|
||||
|
||||
private Instant lastAccessedTime = this.creationTime;
|
||||
|
||||
/**
|
||||
@@ -70,12 +75,10 @@ public final class MapSession implements Session, Serializable {
|
||||
this(generateId());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance with the specified id. This is preferred to the default
|
||||
* constructor when the id is known to prevent unnecessary consumption on entropy
|
||||
* which can be slow.
|
||||
*
|
||||
* @param id the identifier to use
|
||||
*/
|
||||
public MapSession(String id) {
|
||||
@@ -85,7 +88,6 @@ public final class MapSession implements Session, Serializable {
|
||||
|
||||
/**
|
||||
* Creates a new instance from the provided {@link Session}.
|
||||
*
|
||||
* @param session the {@link Session} to initialize this {@link Session} with. Cannot
|
||||
* be null.
|
||||
*/
|
||||
@@ -95,8 +97,7 @@ public final class MapSession implements Session, Serializable {
|
||||
}
|
||||
this.id = session.getId();
|
||||
this.originalId = this.id;
|
||||
this.sessionAttrs = new HashMap<>(
|
||||
session.getAttributeNames().size());
|
||||
this.sessionAttrs = new HashMap<>(session.getAttributeNames().size());
|
||||
for (String attrName : session.getAttributeNames()) {
|
||||
Object attrValue = session.getAttribute(attrName);
|
||||
if (attrValue != null) {
|
||||
@@ -205,7 +206,6 @@ public final class MapSession implements Session, Serializable {
|
||||
* Sets the identifier for this {@link Session}. The id should be a secure random
|
||||
* generated value to prevent malicious users from guessing this value. The default is
|
||||
* a secure random generated identifier.
|
||||
*
|
||||
* @param id the identifier for this session.
|
||||
*/
|
||||
public void setId(String id) {
|
||||
@@ -227,4 +227,5 @@ public final class MapSession implements Session, Serializable {
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 7160779239673823561L;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -49,7 +49,6 @@ public class MapSessionRepository implements SessionRepository<MapSession> {
|
||||
/**
|
||||
* Creates a new instance backed by the provided {@link java.util.Map}. This allows
|
||||
* injecting a distributed {@link java.util.Map}.
|
||||
*
|
||||
* @param sessions the {@link java.util.Map} to use. Cannot be null.
|
||||
*/
|
||||
public MapSessionRepository(Map<String, Session> sessions) {
|
||||
@@ -99,8 +98,7 @@ public class MapSessionRepository implements SessionRepository<MapSession> {
|
||||
public MapSession createSession() {
|
||||
MapSession result = new MapSession();
|
||||
if (this.defaultMaxInactiveInterval != null) {
|
||||
result.setMaxInactiveInterval(
|
||||
Duration.ofSeconds(this.defaultMaxInactiveInterval));
|
||||
result.setMaxInactiveInterval(Duration.ofSeconds(this.defaultMaxInactiveInterval));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -51,7 +51,6 @@ public class ReactiveMapSessionRepository implements ReactiveSessionRepository<M
|
||||
/**
|
||||
* Creates a new instance backed by the provided {@link Map}. This allows injecting a
|
||||
* distributed {@link Map}.
|
||||
*
|
||||
* @param sessions the {@link Map} to use. Cannot be null.
|
||||
*/
|
||||
public ReactiveMapSessionRepository(Map<String, Session> sessions) {
|
||||
@@ -101,8 +100,7 @@ public class ReactiveMapSessionRepository implements ReactiveSessionRepository<M
|
||||
return Mono.defer(() -> {
|
||||
MapSession result = new MapSession();
|
||||
if (this.defaultMaxInactiveInterval != null) {
|
||||
result.setMaxInactiveInterval(
|
||||
Duration.ofSeconds(this.defaultMaxInactiveInterval));
|
||||
result.setMaxInactiveInterval(Duration.ofSeconds(this.defaultMaxInactiveInterval));
|
||||
}
|
||||
return Mono.just(result);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -36,7 +36,6 @@ public interface ReactiveSessionRepository<S extends Session> {
|
||||
* persisted. For example, the implementation returned might keep track of the changes
|
||||
* ensuring that only the delta needs to be persisted on a save.
|
||||
* </p>
|
||||
*
|
||||
* @return a new {@link Session} that is capable of being persisted by this
|
||||
* {@link ReactiveSessionRepository}
|
||||
*/
|
||||
@@ -51,7 +50,6 @@ public interface ReactiveSessionRepository<S extends Session> {
|
||||
* returning a {@link Session} that immediately persists any changes. In this case,
|
||||
* this method may not actually do anything.
|
||||
* </p>
|
||||
*
|
||||
* @param session the {@link Session} to save
|
||||
* @return indicator of operation completion
|
||||
*/
|
||||
@@ -60,7 +58,6 @@ public interface ReactiveSessionRepository<S extends Session> {
|
||||
/**
|
||||
* Gets the {@link Session} by the {@link Session#getId()} or null if no
|
||||
* {@link Session} is found.
|
||||
*
|
||||
* @param id the {@link Session#getId()} to lookup
|
||||
* @return the {@link Session} by the {@link Session#getId()} or null if no
|
||||
* {@link Session} is found.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -32,13 +32,13 @@ public interface Session {
|
||||
|
||||
/**
|
||||
* Gets a unique string that identifies the {@link Session}.
|
||||
*
|
||||
* @return a unique string that identifies the {@link Session}
|
||||
*/
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* Changes the session id. After invoking the {@link #getId()} will return a new identifier.
|
||||
* Changes the session id. After invoking the {@link #getId()} will return a new
|
||||
* identifier.
|
||||
* @return the new session id which {@link #getId()} will now return
|
||||
*/
|
||||
String changeSessionId();
|
||||
@@ -46,7 +46,6 @@ public interface Session {
|
||||
/**
|
||||
* Gets the Object associated with the specified name or null if no Object is
|
||||
* associated to that name.
|
||||
*
|
||||
* @param <T> the return type of the attribute
|
||||
* @param attributeName the name of the attribute to get
|
||||
* @return the Object associated with the specified name or null if no Object is
|
||||
@@ -65,8 +64,7 @@ public interface Session {
|
||||
default <T> T getRequiredAttribute(String name) {
|
||||
T result = getAttribute(name);
|
||||
if (result == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Required attribute '" + name + "' is missing.");
|
||||
throw new IllegalArgumentException("Required attribute '" + name + "' is missing.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -88,7 +86,6 @@ public interface Session {
|
||||
* Gets the attribute names that have a value associated with it. Each value can be
|
||||
* passed into {@link org.springframework.session.Session#getAttribute(String)} to
|
||||
* obtain the attribute value.
|
||||
*
|
||||
* @return the attribute names that have a value associated with it.
|
||||
* @see #getAttribute(String)
|
||||
*/
|
||||
@@ -98,7 +95,6 @@ public interface Session {
|
||||
* Sets the attribute value for the provided attribute name. If the attributeValue is
|
||||
* null, it has the same result as removing the attribute with
|
||||
* {@link org.springframework.session.Session#removeAttribute(String)} .
|
||||
*
|
||||
* @param attributeName the attribute name to set
|
||||
* @param attributeValue the value of the attribute to set. If null, the attribute
|
||||
* will be removed.
|
||||
@@ -113,21 +109,18 @@ public interface Session {
|
||||
|
||||
/**
|
||||
* Gets the time when this session was created.
|
||||
*
|
||||
* @return the time when this session was created.
|
||||
*/
|
||||
Instant getCreationTime();
|
||||
|
||||
/**
|
||||
* Sets the last accessed time.
|
||||
*
|
||||
* @param lastAccessedTime the last accessed time
|
||||
*/
|
||||
void setLastAccessedTime(Instant lastAccessedTime);
|
||||
|
||||
/**
|
||||
* Gets the last time this {@link Session} was accessed.
|
||||
*
|
||||
* @return the last time the client sent a request associated with the session
|
||||
*/
|
||||
Instant getLastAccessedTime();
|
||||
@@ -135,7 +128,6 @@ public interface Session {
|
||||
/**
|
||||
* Sets the maximum inactive interval between requests before this session will be
|
||||
* invalidated. A negative time indicates that the session will never timeout.
|
||||
*
|
||||
* @param interval the amount of time that the {@link Session} should be kept alive
|
||||
* between client requests.
|
||||
*/
|
||||
@@ -144,7 +136,6 @@ public interface Session {
|
||||
/**
|
||||
* Gets the maximum inactive interval between requests before this session will be
|
||||
* invalidated. A negative time indicates that the session will never timeout.
|
||||
*
|
||||
* @return the maximum inactive interval between requests before this session will be
|
||||
* invalidated. A negative time indicates that the session will never timeout.
|
||||
*/
|
||||
@@ -152,7 +143,6 @@ public interface Session {
|
||||
|
||||
/**
|
||||
* Returns true if the session is expired.
|
||||
*
|
||||
* @return true if the session is expired, else false.
|
||||
*/
|
||||
boolean isExpired();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -34,7 +34,6 @@ public interface SessionRepository<S extends Session> {
|
||||
* persisted. For example, the implementation returned might keep track of the changes
|
||||
* ensuring that only the delta needs to be persisted on a save.
|
||||
* </p>
|
||||
*
|
||||
* @return a new {@link Session} that is capable of being persisted by this
|
||||
* {@link SessionRepository}
|
||||
*/
|
||||
@@ -49,7 +48,6 @@ public interface SessionRepository<S extends Session> {
|
||||
* returning a {@link Session} that immediately persists any changes. In this case,
|
||||
* this method may not actually do anything.
|
||||
* </p>
|
||||
*
|
||||
* @param session the {@link Session} to save
|
||||
*/
|
||||
void save(S session);
|
||||
@@ -57,7 +55,6 @@ public interface SessionRepository<S extends Session> {
|
||||
/**
|
||||
* Gets the {@link Session} by the {@link Session#getId()} or null if no
|
||||
* {@link Session} is found.
|
||||
*
|
||||
* @param id the {@link org.springframework.session.Session#getId()} to lookup
|
||||
* @return the {@link Session} by the {@link Session#getId()} or null if no
|
||||
* {@link Session} is found.
|
||||
@@ -70,4 +67,5 @@ public interface SessionRepository<S extends Session> {
|
||||
* @param id the {@link org.springframework.session.Session#getId()} to delete
|
||||
*/
|
||||
void deleteById(String id);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -76,4 +76,5 @@ import org.springframework.session.events.SessionDestroyedEvent;
|
||||
@Import(SpringHttpSessionConfiguration.class)
|
||||
@Configuration
|
||||
public @interface EnableSpringHttpSession {
|
||||
|
||||
}
|
||||
|
||||
@@ -88,7 +88,6 @@ import org.springframework.util.ObjectUtils;
|
||||
* @author Rob Winch
|
||||
* @author Vedran Pavic
|
||||
* @since 1.1
|
||||
*
|
||||
* @see EnableSpringHttpSession
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@@ -110,8 +109,7 @@ public class SpringHttpSessionConfiguration implements ApplicationContextAware {
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
CookieSerializer cookieSerializer = (this.cookieSerializer != null)
|
||||
? this.cookieSerializer
|
||||
CookieSerializer cookieSerializer = (this.cookieSerializer != null) ? this.cookieSerializer
|
||||
: createDefaultCookieSerializer();
|
||||
this.defaultHttpSessionIdResolver.setCookieSerializer(cookieSerializer);
|
||||
}
|
||||
@@ -124,21 +122,16 @@ public class SpringHttpSessionConfiguration implements ApplicationContextAware {
|
||||
@Bean
|
||||
public <S extends Session> SessionRepositoryFilter<? extends Session> springSessionRepositoryFilter(
|
||||
SessionRepository<S> sessionRepository) {
|
||||
SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<>(
|
||||
sessionRepository);
|
||||
SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<>(sessionRepository);
|
||||
sessionRepositoryFilter.setHttpSessionIdResolver(this.httpSessionIdResolver);
|
||||
return sessionRepositoryFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
if (ClassUtils.isPresent(
|
||||
"org.springframework.security.web.authentication.RememberMeServices",
|
||||
null)) {
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
if (ClassUtils.isPresent("org.springframework.security.web.authentication.RememberMeServices", null)) {
|
||||
this.usesSpringSessionRememberMeServices = !ObjectUtils
|
||||
.isEmpty(applicationContext
|
||||
.getBeanNamesForType(SpringSessionRememberMeServices.class));
|
||||
.isEmpty(applicationContext.getBeanNamesForType(SpringSessionRememberMeServices.class));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,8 +163,7 @@ public class SpringHttpSessionConfiguration implements ApplicationContextAware {
|
||||
sessionCookieConfig = this.servletContext.getSessionCookieConfig();
|
||||
}
|
||||
catch (UnsupportedOperationException ex) {
|
||||
this.logger
|
||||
.warn("Unable to obtain SessionCookieConfig: " + ex.getMessage());
|
||||
this.logger.warn("Unable to obtain SessionCookieConfig: " + ex.getMessage());
|
||||
}
|
||||
if (sessionCookieConfig != null) {
|
||||
if (sessionCookieConfig.getName() != null) {
|
||||
@@ -189,8 +181,7 @@ public class SpringHttpSessionConfiguration implements ApplicationContextAware {
|
||||
}
|
||||
}
|
||||
if (this.usesSpringSessionRememberMeServices) {
|
||||
cookieSerializer.setRememberMeRequestAttribute(
|
||||
SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR);
|
||||
cookieSerializer.setRememberMeRequestAttribute(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR);
|
||||
}
|
||||
return cookieSerializer;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -23,9 +23,10 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Add this annotation to a {@code @Configuration} class to configure a {@code WebSessionManager} for a WebFlux
|
||||
* application. This annotation assumes a {@code ReactiveSessionRepository} is defined somewhere in the application
|
||||
* context. If not, it will fail with a clear error message. For example:
|
||||
* Add this annotation to a {@code @Configuration} class to configure a
|
||||
* {@code WebSessionManager} for a WebFlux application. This annotation assumes a
|
||||
* {@code ReactiveSessionRepository} is defined somewhere in the application context. If
|
||||
* not, it will fail with a clear error message. For example:
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
@@ -39,8 +40,7 @@ import org.springframework.context.annotation.Import;
|
||||
* }
|
||||
*
|
||||
* }
|
||||
* </code>
|
||||
* </pre>
|
||||
* </code> </pre>
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @since 2.0
|
||||
@@ -51,4 +51,5 @@ import org.springframework.context.annotation.Import;
|
||||
@Import(SpringWebSessionConfiguration.class)
|
||||
@Configuration
|
||||
public @interface EnableSpringWebSession {
|
||||
|
||||
}
|
||||
|
||||
@@ -27,12 +27,12 @@ import org.springframework.web.server.session.WebSessionIdResolver;
|
||||
import org.springframework.web.server.session.WebSessionManager;
|
||||
|
||||
/**
|
||||
* Wire up a {@link WebSessionManager} using a Reactive {@link ReactiveSessionRepository} from the application context.
|
||||
* Wire up a {@link WebSessionManager} using a Reactive {@link ReactiveSessionRepository}
|
||||
* from the application context.
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @author Rob Winch
|
||||
* @since 2.0
|
||||
*
|
||||
* @see EnableSpringWebSession
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@@ -45,10 +45,11 @@ public class SpringWebSessionConfiguration {
|
||||
private WebSessionIdResolver webSessionIdResolver;
|
||||
|
||||
/**
|
||||
* Configure a {@link WebSessionManager} using a provided {@link ReactiveSessionRepository}.
|
||||
*
|
||||
* Configure a {@link WebSessionManager} using a provided
|
||||
* {@link ReactiveSessionRepository}.
|
||||
* @param repository a bean that implements {@link ReactiveSessionRepository}.
|
||||
* @return a configured {@link WebSessionManager} registered with a preconfigured name.
|
||||
* @return a configured {@link WebSessionManager} registered with a preconfigured
|
||||
* name.
|
||||
*/
|
||||
@Bean(WebHttpHandlerBuilder.WEB_SESSION_MANAGER_BEAN_NAME)
|
||||
public WebSessionManager webSessionManager(ReactiveSessionRepository<? extends Session> repository) {
|
||||
@@ -62,4 +63,5 @@ public class SpringWebSessionConfiguration {
|
||||
|
||||
return manager;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -44,7 +44,6 @@ public abstract class AbstractSessionEvent extends ApplicationEvent {
|
||||
* Gets the {@link Session} that was destroyed. For some {@link SessionRepository}
|
||||
* implementations it may not be possible to get the original session in which case
|
||||
* this may be null.
|
||||
*
|
||||
* @param <S> the type of Session
|
||||
* @return the expired {@link Session} or null if the data store does not support
|
||||
* obtaining it
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -36,23 +36,18 @@ import org.springframework.session.SessionRepository;
|
||||
* @author Vedran Pavic
|
||||
* @since 1.3
|
||||
*/
|
||||
class SpringSessionBackedSessionInformation<S extends Session>
|
||||
extends SessionInformation {
|
||||
class SpringSessionBackedSessionInformation<S extends Session> extends SessionInformation {
|
||||
|
||||
static final String EXPIRED_ATTR = SpringSessionBackedSessionInformation.class
|
||||
.getName() + ".EXPIRED";
|
||||
static final String EXPIRED_ATTR = SpringSessionBackedSessionInformation.class.getName() + ".EXPIRED";
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(SpringSessionBackedSessionInformation.class);
|
||||
private static final Log logger = LogFactory.getLog(SpringSessionBackedSessionInformation.class);
|
||||
|
||||
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
|
||||
|
||||
private final SessionRepository<S> sessionRepository;
|
||||
|
||||
SpringSessionBackedSessionInformation(S session,
|
||||
SessionRepository<S> sessionRepository) {
|
||||
super(resolvePrincipal(session), session.getId(),
|
||||
Date.from(session.getLastAccessedTime()));
|
||||
SpringSessionBackedSessionInformation(S session, SessionRepository<S> sessionRepository) {
|
||||
super(resolvePrincipal(session), session.getId(), Date.from(session.getLastAccessedTime()));
|
||||
this.sessionRepository = sessionRepository;
|
||||
Boolean expired = session.getAttribute(EXPIRED_ATTR);
|
||||
if (Boolean.TRUE.equals(expired)) {
|
||||
@@ -62,20 +57,16 @@ class SpringSessionBackedSessionInformation<S extends Session>
|
||||
|
||||
/**
|
||||
* Tries to determine the principal's name from the given Session.
|
||||
*
|
||||
* @param session the session
|
||||
* @return the principal's name, or empty String if it couldn't be determined
|
||||
*/
|
||||
private static String resolvePrincipal(Session session) {
|
||||
String principalName = session
|
||||
.getAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
|
||||
String principalName = session.getAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
|
||||
if (principalName != null) {
|
||||
return principalName;
|
||||
}
|
||||
SecurityContext securityContext = session
|
||||
.getAttribute(SPRING_SECURITY_CONTEXT);
|
||||
if (securityContext != null
|
||||
&& securityContext.getAuthentication() != null) {
|
||||
SecurityContext securityContext = session.getAttribute(SPRING_SECURITY_CONTEXT);
|
||||
if (securityContext != null && securityContext.getAuthentication() != null) {
|
||||
return securityContext.getAuthentication().getName();
|
||||
}
|
||||
return "";
|
||||
@@ -84,9 +75,8 @@ class SpringSessionBackedSessionInformation<S extends Session>
|
||||
@Override
|
||||
public void expireNow() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Expiring session " + getSessionId() + " for user '"
|
||||
+ getPrincipal() + "', presumably because maximum allowed concurrent "
|
||||
+ "sessions was exceeded");
|
||||
logger.debug("Expiring session " + getSessionId() + " for user '" + getPrincipal()
|
||||
+ "', presumably because maximum allowed concurrent " + "sessions was exceeded");
|
||||
}
|
||||
super.expireNow();
|
||||
S session = this.sessionRepository.findById(getSessionId());
|
||||
@@ -95,8 +85,7 @@ class SpringSessionBackedSessionInformation<S extends Session>
|
||||
this.sessionRepository.save(session);
|
||||
}
|
||||
else {
|
||||
logger.info("Could not find Session with id " + getSessionId()
|
||||
+ " to mark as expired");
|
||||
logger.info("Could not find Session with id " + getSessionId() + " to mark as expired");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -44,13 +44,11 @@ import org.springframework.util.Assert;
|
||||
* @author Vedran Pavic
|
||||
* @since 1.3
|
||||
*/
|
||||
public class SpringSessionBackedSessionRegistry<S extends Session>
|
||||
implements SessionRegistry {
|
||||
public class SpringSessionBackedSessionRegistry<S extends Session> implements SessionRegistry {
|
||||
|
||||
private final FindByIndexNameSessionRepository<S> sessionRepository;
|
||||
|
||||
public SpringSessionBackedSessionRegistry(
|
||||
FindByIndexNameSessionRepository<S> sessionRepository) {
|
||||
public SpringSessionBackedSessionRegistry(FindByIndexNameSessionRepository<S> sessionRepository) {
|
||||
Assert.notNull(sessionRepository, "sessionRepository cannot be null");
|
||||
this.sessionRepository = sessionRepository;
|
||||
}
|
||||
@@ -63,16 +61,13 @@ public class SpringSessionBackedSessionRegistry<S extends Session>
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SessionInformation> getAllSessions(Object principal,
|
||||
boolean includeExpiredSessions) {
|
||||
Collection<S> sessions = this.sessionRepository
|
||||
.findByPrincipalName(name(principal)).values();
|
||||
public List<SessionInformation> getAllSessions(Object principal, boolean includeExpiredSessions) {
|
||||
Collection<S> sessions = this.sessionRepository.findByPrincipalName(name(principal)).values();
|
||||
List<SessionInformation> infos = new ArrayList<>();
|
||||
for (S session : sessions) {
|
||||
if (includeExpiredSessions || !Boolean.TRUE.equals(session
|
||||
.getAttribute(SpringSessionBackedSessionInformation.EXPIRED_ATTR))) {
|
||||
infos.add(new SpringSessionBackedSessionInformation<>(session,
|
||||
this.sessionRepository));
|
||||
if (includeExpiredSessions
|
||||
|| !Boolean.TRUE.equals(session.getAttribute(SpringSessionBackedSessionInformation.EXPIRED_ATTR))) {
|
||||
infos.add(new SpringSessionBackedSessionInformation<>(session, this.sessionRepository));
|
||||
}
|
||||
}
|
||||
return infos;
|
||||
@@ -82,8 +77,7 @@ public class SpringSessionBackedSessionRegistry<S extends Session>
|
||||
public SessionInformation getSessionInformation(String sessionId) {
|
||||
S session = this.sessionRepository.findById(sessionId);
|
||||
if (session != null) {
|
||||
return new SpringSessionBackedSessionInformation<>(session,
|
||||
this.sessionRepository);
|
||||
return new SpringSessionBackedSessionInformation<>(session, this.sessionRepository);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -111,7 +105,6 @@ public class SpringSessionBackedSessionRegistry<S extends Session>
|
||||
|
||||
/**
|
||||
* Derives a String name for the given principal.
|
||||
*
|
||||
* @param principal as provided by Spring Security
|
||||
* @return name of the principal, or its {@code toString()} representation if no name
|
||||
* could be derived
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -36,21 +36,19 @@ import org.springframework.util.Assert;
|
||||
* @author Vedran Pavic
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class SpringSessionRememberMeServices
|
||||
implements RememberMeServices, LogoutHandler {
|
||||
public class SpringSessionRememberMeServices implements RememberMeServices, LogoutHandler {
|
||||
|
||||
/**
|
||||
* Remember-me login request attribute name.
|
||||
*/
|
||||
public static final String REMEMBER_ME_LOGIN_ATTR = SpringSessionRememberMeServices.class
|
||||
.getName() + "REMEMBER_ME_LOGIN_ATTR";
|
||||
public static final String REMEMBER_ME_LOGIN_ATTR = SpringSessionRememberMeServices.class.getName()
|
||||
+ "REMEMBER_ME_LOGIN_ATTR";
|
||||
|
||||
private static final String DEFAULT_REMEMBERME_PARAMETER = "remember-me";
|
||||
|
||||
private static final int THIRTY_DAYS_SECONDS = 2592000;
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(SpringSessionRememberMeServices.class);
|
||||
private static final Log logger = LogFactory.getLog(SpringSessionRememberMeServices.class);
|
||||
|
||||
private String rememberMeParameterName = DEFAULT_REMEMBERME_PARAMETER;
|
||||
|
||||
@@ -61,22 +59,19 @@ public class SpringSessionRememberMeServices
|
||||
private String sessionAttrToDeleteOnLoginFail = HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY;
|
||||
|
||||
@Override
|
||||
public final Authentication autoLogin(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
public final Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void loginFail(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
public final void loginFail(HttpServletRequest request, HttpServletResponse response) {
|
||||
logout(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void loginSuccess(HttpServletRequest request,
|
||||
HttpServletResponse response, Authentication successfulAuthentication) {
|
||||
if (!this.alwaysRemember
|
||||
&& !rememberMeRequested(request, this.rememberMeParameterName)) {
|
||||
public final void loginSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication successfulAuthentication) {
|
||||
if (!this.alwaysRemember && !rememberMeRequested(request, this.rememberMeParameterName)) {
|
||||
logger.debug("Remember-me login not requested.");
|
||||
return;
|
||||
}
|
||||
@@ -103,8 +98,7 @@ public class SpringSessionRememberMeServices
|
||||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Did not send remember-me cookie (principal did not set "
|
||||
+ "parameter '" + parameter + "')");
|
||||
logger.debug("Did not send remember-me cookie (principal did not set " + "parameter '" + parameter + "')");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -116,8 +110,7 @@ public class SpringSessionRememberMeServices
|
||||
* @param rememberMeParameterName the request parameter
|
||||
*/
|
||||
public void setRememberMeParameterName(String rememberMeParameterName) {
|
||||
Assert.hasText(rememberMeParameterName,
|
||||
"rememberMeParameterName cannot be empty or null");
|
||||
Assert.hasText(rememberMeParameterName, "rememberMeParameterName cannot be empty or null");
|
||||
this.rememberMeParameterName = rememberMeParameterName;
|
||||
}
|
||||
|
||||
@@ -130,8 +123,7 @@ public class SpringSessionRememberMeServices
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) {
|
||||
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
|
||||
logout(request);
|
||||
}
|
||||
|
||||
@@ -142,4 +134,5 @@ public class SpringSessionRememberMeServices
|
||||
session.removeAttribute(this.sessionAttrToDeleteOnLoginFail);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -71,8 +71,7 @@ import org.springframework.web.filter.DelegatingFilterProxy;
|
||||
*
|
||||
*/
|
||||
@Order(100)
|
||||
public abstract class AbstractHttpSessionApplicationInitializer
|
||||
implements WebApplicationInitializer {
|
||||
public abstract class AbstractHttpSessionApplicationInitializer implements WebApplicationInitializer {
|
||||
|
||||
private static final String SERVLET_CONTEXT_PREFIX = "org.springframework.web.servlet.FrameworkServlet.CONTEXT.";
|
||||
|
||||
@@ -98,12 +97,10 @@ public abstract class AbstractHttpSessionApplicationInitializer
|
||||
/**
|
||||
* Creates a new instance that will instantiate the {@link ContextLoaderListener} with
|
||||
* the specified classes.
|
||||
*
|
||||
* @param configurationClasses {@code @Configuration} classes that will be used to
|
||||
* configure the context
|
||||
*/
|
||||
protected AbstractHttpSessionApplicationInitializer(
|
||||
Class<?>... configurationClasses) {
|
||||
protected AbstractHttpSessionApplicationInitializer(Class<?>... configurationClasses) {
|
||||
this.configurationClasses = configurationClasses;
|
||||
}
|
||||
|
||||
@@ -125,8 +122,7 @@ public abstract class AbstractHttpSessionApplicationInitializer
|
||||
*/
|
||||
private void insertSessionRepositoryFilter(ServletContext servletContext) {
|
||||
String filterName = DEFAULT_FILTER_NAME;
|
||||
DelegatingFilterProxy springSessionRepositoryFilter = new DelegatingFilterProxy(
|
||||
filterName);
|
||||
DelegatingFilterProxy springSessionRepositoryFilter = new DelegatingFilterProxy(filterName);
|
||||
String contextAttribute = getWebApplicationContextAttribute();
|
||||
if (contextAttribute != null) {
|
||||
springSessionRepositoryFilter.setContextAttribute(contextAttribute);
|
||||
@@ -138,7 +134,6 @@ public abstract class AbstractHttpSessionApplicationInitializer
|
||||
* Inserts the provided {@link Filter}s before existing {@link Filter}s using default
|
||||
* generated names, {@link #getSessionDispatcherTypes()}, and
|
||||
* {@link #isAsyncSessionSupported()}.
|
||||
*
|
||||
* @param servletContext the {@link ServletContext} to use
|
||||
* @param filters the {@link Filter}s to register
|
||||
*/
|
||||
@@ -150,7 +145,6 @@ public abstract class AbstractHttpSessionApplicationInitializer
|
||||
* Inserts the provided {@link Filter}s after existing {@link Filter}s using default
|
||||
* generated names, {@link #getSessionDispatcherTypes()}, and
|
||||
* {@link #isAsyncSessionSupported()}.
|
||||
*
|
||||
* @param servletContext the {@link ServletContext} to use
|
||||
* @param filters the {@link Filter}s to register
|
||||
*/
|
||||
@@ -161,22 +155,18 @@ public abstract class AbstractHttpSessionApplicationInitializer
|
||||
/**
|
||||
* Registers the provided {@link Filter}s using default generated names,
|
||||
* {@link #getSessionDispatcherTypes()}, and {@link #isAsyncSessionSupported()}.
|
||||
*
|
||||
* @param servletContext the {@link ServletContext} to use
|
||||
* @param insertBeforeOtherFilters if true, will insert the provided {@link Filter}s
|
||||
* before other {@link Filter}s. Otherwise, will insert the {@link Filter}s after
|
||||
* other {@link Filter}s.
|
||||
* @param filters the {@link Filter}s to register
|
||||
*/
|
||||
private void registerFilters(ServletContext servletContext,
|
||||
boolean insertBeforeOtherFilters, Filter... filters) {
|
||||
private void registerFilters(ServletContext servletContext, boolean insertBeforeOtherFilters, Filter... filters) {
|
||||
Assert.notEmpty(filters, "filters cannot be null or empty");
|
||||
|
||||
for (Filter filter : filters) {
|
||||
if (filter == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"filters cannot contain null values. Got "
|
||||
+ Arrays.asList(filters));
|
||||
throw new IllegalArgumentException("filters cannot contain null values. Got " + Arrays.asList(filters));
|
||||
}
|
||||
String filterName = Conventions.getVariableName(filter);
|
||||
registerFilter(servletContext, insertBeforeOtherFilters, filterName, filter);
|
||||
@@ -186,25 +176,22 @@ public abstract class AbstractHttpSessionApplicationInitializer
|
||||
/**
|
||||
* Registers the provided filter using the {@link #isAsyncSessionSupported()} and
|
||||
* {@link #getSessionDispatcherTypes()}.
|
||||
*
|
||||
* @param servletContext the servlet context
|
||||
* @param insertBeforeOtherFilters should this Filter be inserted before or after
|
||||
* other {@link Filter}
|
||||
* @param filterName the filter name
|
||||
* @param filter the filter
|
||||
*/
|
||||
private void registerFilter(ServletContext servletContext,
|
||||
boolean insertBeforeOtherFilters, String filterName, Filter filter) {
|
||||
private void registerFilter(ServletContext servletContext, boolean insertBeforeOtherFilters, String filterName,
|
||||
Filter filter) {
|
||||
Dynamic registration = servletContext.addFilter(filterName, filter);
|
||||
if (registration == null) {
|
||||
throw new IllegalStateException(
|
||||
"Duplicate Filter registration for '" + filterName
|
||||
+ "'. Check to ensure the Filter is only configured once.");
|
||||
throw new IllegalStateException("Duplicate Filter registration for '" + filterName
|
||||
+ "'. Check to ensure the Filter is only configured once.");
|
||||
}
|
||||
registration.setAsyncSupported(isAsyncSessionSupported());
|
||||
EnumSet<DispatcherType> dispatcherTypes = getSessionDispatcherTypes();
|
||||
registration.addMappingForUrlPatterns(dispatcherTypes, !insertBeforeOtherFilters,
|
||||
"/*");
|
||||
registration.addMappingForUrlPatterns(dispatcherTypes, !insertBeforeOtherFilters, "/*");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -218,7 +205,6 @@ public abstract class AbstractHttpSessionApplicationInitializer
|
||||
* {@link ApplicationContext} is used to look up the springSessionRepositoryFilter
|
||||
* bean.
|
||||
* </p>
|
||||
*
|
||||
* @return the {@link DelegatingFilterProxy#getContextAttribute()} or null if the
|
||||
* parent {@link ApplicationContext} should be used
|
||||
*/
|
||||
@@ -241,7 +227,6 @@ public abstract class AbstractHttpSessionApplicationInitializer
|
||||
* name, you can return "dispatcher" from this method to use the DispatcherServlet's
|
||||
* {@link WebApplicationContext}.
|
||||
* </p>
|
||||
*
|
||||
* @return the {@code <servlet-name>} of the DispatcherServlet to use its
|
||||
* {@link WebApplicationContext} or null (default) to use the parent
|
||||
* {@link ApplicationContext}.
|
||||
@@ -271,17 +256,16 @@ public abstract class AbstractHttpSessionApplicationInitializer
|
||||
* @return the {@link DispatcherType} for the filter
|
||||
*/
|
||||
protected EnumSet<DispatcherType> getSessionDispatcherTypes() {
|
||||
return EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR,
|
||||
DispatcherType.ASYNC);
|
||||
return EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR, DispatcherType.ASYNC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the springSessionRepositoryFilter should be marked as supporting
|
||||
* asynch. Default is true.
|
||||
*
|
||||
* @return true if springSessionRepositoryFilter should be marked as supporting asynch
|
||||
*/
|
||||
protected boolean isAsyncSessionSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -63,8 +63,8 @@ import org.springframework.session.web.http.CookieSerializer.CookieValue;
|
||||
*/
|
||||
public final class CookieHttpSessionIdResolver implements HttpSessionIdResolver {
|
||||
|
||||
private static final String WRITTEN_SESSION_ID_ATTR = CookieHttpSessionIdResolver.class
|
||||
.getName().concat(".WRITTEN_SESSION_ID_ATTR");
|
||||
private static final String WRITTEN_SESSION_ID_ATTR = CookieHttpSessionIdResolver.class.getName()
|
||||
.concat(".WRITTEN_SESSION_ID_ATTR");
|
||||
|
||||
private CookieSerializer cookieSerializer = new DefaultCookieSerializer();
|
||||
|
||||
@@ -74,14 +74,12 @@ public final class CookieHttpSessionIdResolver implements HttpSessionIdResolver
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSessionId(HttpServletRequest request, HttpServletResponse response,
|
||||
String sessionId) {
|
||||
public void setSessionId(HttpServletRequest request, HttpServletResponse response, String sessionId) {
|
||||
if (sessionId.equals(request.getAttribute(WRITTEN_SESSION_ID_ATTR))) {
|
||||
return;
|
||||
}
|
||||
request.setAttribute(WRITTEN_SESSION_ID_ATTR, sessionId);
|
||||
this.cookieSerializer
|
||||
.writeCookieValue(new CookieValue(request, response, sessionId));
|
||||
this.cookieSerializer.writeCookieValue(new CookieValue(request, response, sessionId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,7 +89,6 @@ public final class CookieHttpSessionIdResolver implements HttpSessionIdResolver
|
||||
|
||||
/**
|
||||
* Sets the {@link CookieSerializer} to be used.
|
||||
*
|
||||
* @param cookieSerializer the cookieSerializer to set. Cannot be null.
|
||||
*/
|
||||
public void setCookieSerializer(CookieSerializer cookieSerializer) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -32,7 +32,6 @@ public interface CookieSerializer {
|
||||
|
||||
/**
|
||||
* Writes a given {@link CookieValue} to the provided {@link HttpServletResponse}.
|
||||
*
|
||||
* @param cookieValue the {@link CookieValue} to write to
|
||||
* {@link CookieValue#getResponse()}. Cannot be null.
|
||||
*/
|
||||
@@ -43,7 +42,6 @@ public interface CookieSerializer {
|
||||
* List since there can be multiple {@link Cookie} in a single request with a matching
|
||||
* name. For example, one Cookie may have a path of / and another of /context, but the
|
||||
* path is not transmitted in the request.
|
||||
*
|
||||
* @param request the {@link HttpServletRequest} to read the cookie from. Cannot be
|
||||
* null.
|
||||
* @return the values of all the matching cookies
|
||||
@@ -70,7 +68,6 @@ public interface CookieSerializer {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param request the {@link HttpServletRequest} to use. Useful for determining
|
||||
* the context in which the cookie is set. Cannot be null.
|
||||
* @param response the {@link HttpServletResponse} to use.
|
||||
@@ -78,8 +75,7 @@ public interface CookieSerializer {
|
||||
* modified by the {@link CookieSerializer} when writing to the actual cookie so
|
||||
* long as the original value is returned when the cookie is read.
|
||||
*/
|
||||
public CookieValue(HttpServletRequest request, HttpServletResponse response,
|
||||
String cookieValue) {
|
||||
public CookieValue(HttpServletRequest request, HttpServletResponse response, String cookieValue) {
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
this.cookieValue = cookieValue;
|
||||
@@ -108,7 +104,6 @@ public interface CookieSerializer {
|
||||
* The value to be written. This value may be modified by the
|
||||
* {@link CookieSerializer} before written to the cookie. However, the value must
|
||||
* be the same as the original when it is read back in.
|
||||
*
|
||||
* @return the value to be written
|
||||
*/
|
||||
public String getCookieValue() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -97,15 +97,12 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (this.cookieName.equals(cookie.getName())) {
|
||||
String sessionId = (this.useBase64Encoding
|
||||
? base64Decode(cookie.getValue())
|
||||
: cookie.getValue());
|
||||
String sessionId = (this.useBase64Encoding ? base64Decode(cookie.getValue()) : cookie.getValue());
|
||||
if (sessionId == null) {
|
||||
continue;
|
||||
}
|
||||
if (this.jvmRoute != null && sessionId.endsWith(this.jvmRoute)) {
|
||||
sessionId = sessionId.substring(0,
|
||||
sessionId.length() - this.jvmRoute.length());
|
||||
sessionId = sessionId.substring(0, sessionId.length() - this.jvmRoute.length());
|
||||
}
|
||||
matchingCookieValues.add(sessionId);
|
||||
}
|
||||
@@ -135,11 +132,9 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
int maxAge = getMaxAge(cookieValue);
|
||||
if (maxAge > -1) {
|
||||
sb.append("; Max-Age=").append(cookieValue.getCookieMaxAge());
|
||||
OffsetDateTime expires = (maxAge != 0)
|
||||
? OffsetDateTime.now().plusSeconds(maxAge)
|
||||
OffsetDateTime expires = (maxAge != 0) ? OffsetDateTime.now().plusSeconds(maxAge)
|
||||
: Instant.EPOCH.atOffset(ZoneOffset.UTC);
|
||||
sb.append("; Expires=")
|
||||
.append(expires.format(DateTimeFormatter.RFC_1123_DATE_TIME));
|
||||
sb.append("; Expires=").append(expires.format(DateTimeFormatter.RFC_1123_DATE_TIME));
|
||||
}
|
||||
String domain = getDomainName(request);
|
||||
if (domain != null && domain.length() > 0) {
|
||||
@@ -214,10 +209,8 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
char[] chars = value.toCharArray();
|
||||
for (int i = start; i < end; i++) {
|
||||
char c = chars[i];
|
||||
if (c < 0x21 || c == 0x22 || c == 0x2c || c == 0x3b || c == 0x5c
|
||||
|| c == 0x7f) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid character in cookie value: " + Integer.toString(c));
|
||||
if (c < 0x21 || c == 0x22 || c == 0x2c || c == 0x3b || c == 0x5c || c == 0x7f) {
|
||||
throw new IllegalArgumentException("Invalid character in cookie value: " + Integer.toString(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,8 +218,8 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
private int getMaxAge(CookieValue cookieValue) {
|
||||
int maxAge = cookieValue.getCookieMaxAge();
|
||||
if (maxAge < 0) {
|
||||
if (this.rememberMeRequestAttribute != null && cookieValue.getRequest()
|
||||
.getAttribute(this.rememberMeRequestAttribute) != null) {
|
||||
if (this.rememberMeRequestAttribute != null
|
||||
&& cookieValue.getRequest().getAttribute(this.rememberMeRequestAttribute) != null) {
|
||||
// the cookie is only written at time of session creation, so we rely on
|
||||
// session expiration rather than cookie expiration if remember me is
|
||||
// enabled
|
||||
@@ -247,8 +240,7 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
while (i < chars.length) {
|
||||
prev = cur;
|
||||
cur = chars[i];
|
||||
if (!domainValid.get(cur)
|
||||
|| ((prev == '.' || prev == -1) && (cur == '.' || cur == '-'))
|
||||
if (!domainValid.get(cur) || ((prev == '.' || prev == -1) && (cur == '.' || cur == '-'))
|
||||
|| (prev == '-' && cur == '.')) {
|
||||
throw new IllegalArgumentException("Invalid cookie domain: " + domain);
|
||||
}
|
||||
@@ -270,7 +262,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
/**
|
||||
* Sets if a Cookie marked as secure should be used. The default is to use the value
|
||||
* of {@link HttpServletRequest#isSecure()}.
|
||||
*
|
||||
* @param useSecureCookie determines if the cookie should be marked as secure.
|
||||
*/
|
||||
public void setUseSecureCookie(boolean useSecureCookie) {
|
||||
@@ -279,7 +270,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
|
||||
/**
|
||||
* Sets if a Cookie marked as HTTP Only should be used. The default is true.
|
||||
*
|
||||
* @param useHttpOnlyCookie determines if the cookie should be marked as HTTP Only.
|
||||
*/
|
||||
public void setUseHttpOnlyCookie(boolean useHttpOnlyCookie) {
|
||||
@@ -296,7 +286,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
/**
|
||||
* Sets the path of the Cookie. The default is to use the context path from the
|
||||
* {@link HttpServletRequest}.
|
||||
*
|
||||
* @param cookiePath the path of the Cookie. If null, the default of the context path
|
||||
* will be used.
|
||||
*/
|
||||
@@ -314,7 +303,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
/**
|
||||
* Sets the maxAge property of the Cookie. The default is to delete the cookie when
|
||||
* the browser is closed.
|
||||
*
|
||||
* @param cookieMaxAge the maxAge property of the Cookie
|
||||
*/
|
||||
public void setCookieMaxAge(int cookieMaxAge) {
|
||||
@@ -325,14 +313,12 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
* Sets an explicit Domain Name. This allow the domain of "example.com" to be used
|
||||
* when the request comes from www.example.com. This allows for sharing the cookie
|
||||
* across subdomains. The default is to use the current domain.
|
||||
*
|
||||
* @param domainName the name of the domain to use. (i.e. "example.com")
|
||||
* @throws IllegalStateException if the domainNamePattern is also set
|
||||
*/
|
||||
public void setDomainName(String domainName) {
|
||||
if (this.domainNamePattern != null) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot set both domainName and domainNamePattern");
|
||||
throw new IllegalStateException("Cannot set both domainName and domainNamePattern");
|
||||
}
|
||||
this.domainName = domainName;
|
||||
}
|
||||
@@ -362,18 +348,15 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
* <li>localhost - null</li>
|
||||
* <li>127.0.1.1 - null</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param domainNamePattern the case insensitive pattern to extract the domain name
|
||||
* with
|
||||
* @throws IllegalStateException if the domainName is also set
|
||||
*/
|
||||
public void setDomainNamePattern(String domainNamePattern) {
|
||||
if (this.domainName != null) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot set both domainName and domainNamePattern");
|
||||
throw new IllegalStateException("Cannot set both domainName and domainNamePattern");
|
||||
}
|
||||
this.domainNamePattern = Pattern.compile(domainNamePattern,
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
this.domainNamePattern = Pattern.compile(domainNamePattern, Pattern.CASE_INSENSITIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -390,7 +373,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
* To use set a custom route on each JVM instance and setup a frontend proxy to
|
||||
* forward all requests to the JVM based on the route.
|
||||
* </p>
|
||||
*
|
||||
* @param jvmRoute the JVM Route to use (i.e. "node01jvmA", "n01ja", etc)
|
||||
*/
|
||||
public void setJvmRoute(String jvmRoute) {
|
||||
@@ -401,7 +383,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
* Set if the Base64 encoding of cookie value should be used. This is valuable in
|
||||
* order to support <a href="https://tools.ietf.org/html/rfc6265">RFC 6265</a> which
|
||||
* recommends using Base 64 encoding to the cookie value.
|
||||
*
|
||||
* @param useBase64Encoding the flag to indicate whether to use Base64 encoding
|
||||
*/
|
||||
public void setUseBase64Encoding(boolean useBase64Encoding) {
|
||||
@@ -416,8 +397,7 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
*/
|
||||
public void setRememberMeRequestAttribute(String rememberMeRequestAttribute) {
|
||||
if (rememberMeRequestAttribute == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"rememberMeRequestAttribute cannot be null");
|
||||
throw new IllegalArgumentException("rememberMeRequestAttribute cannot be null");
|
||||
}
|
||||
this.rememberMeRequestAttribute = rememberMeRequestAttribute;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -98,13 +98,11 @@ public class HeaderHttpSessionIdResolver implements HttpSessionIdResolver {
|
||||
@Override
|
||||
public List<String> resolveSessionIds(HttpServletRequest request) {
|
||||
String headerValue = request.getHeader(this.headerName);
|
||||
return (headerValue != null) ? Collections.singletonList(headerValue)
|
||||
: Collections.emptyList();
|
||||
return (headerValue != null) ? Collections.singletonList(headerValue) : Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSessionId(HttpServletRequest request, HttpServletResponse response,
|
||||
String sessionId) {
|
||||
public void setSessionId(HttpServletRequest request, HttpServletResponse response, String sessionId) {
|
||||
response.setHeader(this.headerName, sessionId);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -142,8 +142,8 @@ class HttpSessionAdapter<S extends Session> implements HttpSession {
|
||||
if (value != oldValue) {
|
||||
if (oldValue instanceof HttpSessionBindingListener) {
|
||||
try {
|
||||
((HttpSessionBindingListener) oldValue).valueUnbound(
|
||||
new HttpSessionBindingEvent(this, name, oldValue));
|
||||
((HttpSessionBindingListener) oldValue)
|
||||
.valueUnbound(new HttpSessionBindingEvent(this, name, oldValue));
|
||||
}
|
||||
catch (Throwable th) {
|
||||
logger.error("Error invoking session binding event listener", th);
|
||||
@@ -151,8 +151,7 @@ class HttpSessionAdapter<S extends Session> implements HttpSession {
|
||||
}
|
||||
if (value instanceof HttpSessionBindingListener) {
|
||||
try {
|
||||
((HttpSessionBindingListener) value)
|
||||
.valueBound(new HttpSessionBindingEvent(this, name, value));
|
||||
((HttpSessionBindingListener) value).valueBound(new HttpSessionBindingEvent(this, name, value));
|
||||
}
|
||||
catch (Throwable th) {
|
||||
logger.error("Error invoking session binding event listener", th);
|
||||
@@ -173,8 +172,7 @@ class HttpSessionAdapter<S extends Session> implements HttpSession {
|
||||
this.session.removeAttribute(name);
|
||||
if (oldValue instanceof HttpSessionBindingListener) {
|
||||
try {
|
||||
((HttpSessionBindingListener) oldValue)
|
||||
.valueUnbound(new HttpSessionBindingEvent(this, name, oldValue));
|
||||
((HttpSessionBindingListener) oldValue).valueUnbound(new HttpSessionBindingEvent(this, name, oldValue));
|
||||
}
|
||||
catch (Throwable th) {
|
||||
logger.error("Error invoking session binding event listener", th);
|
||||
@@ -205,8 +203,7 @@ class HttpSessionAdapter<S extends Session> implements HttpSession {
|
||||
|
||||
private void checkState() {
|
||||
if (this.invalidated) {
|
||||
throw new IllegalStateException(
|
||||
"The HttpSession has already be invalidated.");
|
||||
throw new IllegalStateException("The HttpSession has already be invalidated.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -49,8 +49,7 @@ public interface HttpSessionIdResolver {
|
||||
* @param response the current response
|
||||
* @param sessionId the session id
|
||||
*/
|
||||
void setSessionId(HttpServletRequest request, HttpServletResponse response,
|
||||
String sessionId);
|
||||
void setSessionId(HttpServletRequest request, HttpServletResponse response, String sessionId);
|
||||
|
||||
/**
|
||||
* Instruct the client to end the current session. This method is invoked when a
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -36,6 +36,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
* @since 1.0
|
||||
*/
|
||||
abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private boolean disableOnCommitted;
|
||||
@@ -204,13 +205,11 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
|
||||
/**
|
||||
* Adds the contentLengthToWrite to the total contentWritten size and checks to see if
|
||||
* the response should be written.
|
||||
*
|
||||
* @param contentLengthToWrite the size of the content that is about to be written.
|
||||
*/
|
||||
private void checkContentLength(long contentLengthToWrite) {
|
||||
this.contentWritten += contentLengthToWrite;
|
||||
boolean isBodyFullyWritten = this.contentLength > 0
|
||||
&& this.contentWritten >= this.contentLength;
|
||||
boolean isBodyFullyWritten = this.contentLength > 0 && this.contentWritten >= this.contentLength;
|
||||
int bufferSize = getBufferSize();
|
||||
boolean requiresFlush = bufferSize > 0 && this.contentWritten >= bufferSize;
|
||||
if (isBodyFullyWritten || requiresFlush) {
|
||||
@@ -234,9 +233,11 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
|
||||
* calling the prior to methods that commit the response. We delegate all methods to
|
||||
* the original {@link java.io.PrintWriter} to ensure that the behavior is as close to
|
||||
* the original {@link java.io.PrintWriter} as possible. See SEC-2039
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
private class SaveContextPrintWriter extends PrintWriter {
|
||||
|
||||
private final PrintWriter delegate;
|
||||
|
||||
SaveContextPrintWriter(PrintWriter delegate) {
|
||||
@@ -466,6 +467,7 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
|
||||
trackContentLength(c);
|
||||
return this.delegate.append(c);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -477,6 +479,7 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
|
||||
* @author Rob Winch
|
||||
*/
|
||||
private class SaveContextServletOutputStream extends ServletOutputStream {
|
||||
|
||||
private final ServletOutputStream delegate;
|
||||
|
||||
SaveContextServletOutputStream(ServletOutputStream delegate) {
|
||||
@@ -634,5 +637,7 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
|
||||
public void setWriteListener(WriteListener writeListener) {
|
||||
this.delegate.setWriteListener(writeListener);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,19 +37,18 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* @since 1.0
|
||||
*/
|
||||
abstract class OncePerRequestFilter implements Filter {
|
||||
|
||||
/**
|
||||
* Suffix that gets appended to the filter name for the "already filtered" request
|
||||
* attribute.
|
||||
*/
|
||||
public static final String ALREADY_FILTERED_SUFFIX = ".FILTERED";
|
||||
|
||||
private String alreadyFilteredAttributeName = getClass().getName()
|
||||
.concat(ALREADY_FILTERED_SUFFIX);
|
||||
private String alreadyFilteredAttributeName = getClass().getName().concat(ALREADY_FILTERED_SUFFIX);
|
||||
|
||||
/**
|
||||
* This {@code doFilter} implementation stores a request attribute for
|
||||
* "already filtered", proceeding without filtering again if the attribute is already
|
||||
* there.
|
||||
* This {@code doFilter} implementation stores a request attribute for "already
|
||||
* filtered", proceeding without filtering again if the attribute is already there.
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
* @param filterChain the filter chain
|
||||
@@ -57,21 +56,17 @@ abstract class OncePerRequestFilter implements Filter {
|
||||
* @throws IOException in case of I/O operation exception
|
||||
*/
|
||||
@Override
|
||||
public final void doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
if (!(request instanceof HttpServletRequest)
|
||||
|| !(response instanceof HttpServletResponse)) {
|
||||
throw new ServletException(
|
||||
"OncePerRequestFilter just supports HTTP requests");
|
||||
if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
|
||||
throw new ServletException("OncePerRequestFilter just supports HTTP requests");
|
||||
}
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||
String alreadyFilteredAttributeName = this.alreadyFilteredAttributeName;
|
||||
alreadyFilteredAttributeName = updateForErrorDispatch(
|
||||
alreadyFilteredAttributeName, request);
|
||||
boolean hasAlreadyFilteredAttribute = request
|
||||
.getAttribute(alreadyFilteredAttributeName) != null;
|
||||
alreadyFilteredAttributeName = updateForErrorDispatch(alreadyFilteredAttributeName, request);
|
||||
boolean hasAlreadyFilteredAttribute = request.getAttribute(alreadyFilteredAttributeName) != null;
|
||||
|
||||
if (hasAlreadyFilteredAttribute) {
|
||||
|
||||
@@ -91,9 +86,9 @@ abstract class OncePerRequestFilter implements Filter {
|
||||
}
|
||||
}
|
||||
|
||||
private String updateForErrorDispatch(String alreadyFilteredAttributeName,
|
||||
ServletRequest request) {
|
||||
// Jetty does ERROR dispatch within sendError, so request attribute is still present
|
||||
private String updateForErrorDispatch(String alreadyFilteredAttributeName, ServletRequest request) {
|
||||
// Jetty does ERROR dispatch within sendError, so request attribute is still
|
||||
// present
|
||||
// Use a separate attribute for ERROR dispatches
|
||||
if (DispatcherType.ERROR.equals(request.getDispatcherType())
|
||||
&& request.getAttribute(alreadyFilteredAttributeName) != null) {
|
||||
@@ -108,7 +103,6 @@ abstract class OncePerRequestFilter implements Filter {
|
||||
* <p>
|
||||
* Provides HttpServletRequest and HttpServletResponse arguments instead of the
|
||||
* default ServletRequest and ServletResponse ones.
|
||||
*
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
* @param filterChain the FilterChain
|
||||
@@ -116,9 +110,8 @@ abstract class OncePerRequestFilter implements Filter {
|
||||
* @throws IOException thrown when an I/O exception of some sort has occurred
|
||||
* @see Filter#doFilter
|
||||
*/
|
||||
protected abstract void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException;
|
||||
protected abstract void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException;
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig config) {
|
||||
@@ -127,4 +120,5 @@ abstract class OncePerRequestFilter implements Filter {
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -40,6 +40,7 @@ import org.springframework.web.context.ServletContextAware;
|
||||
*/
|
||||
public class SessionEventHttpSessionListenerAdapter
|
||||
implements ApplicationListener<AbstractSessionEvent>, ServletContextAware {
|
||||
|
||||
private final List<HttpSessionListener> listeners;
|
||||
|
||||
private ServletContext context;
|
||||
@@ -75,8 +76,7 @@ public class SessionEventHttpSessionListenerAdapter
|
||||
|
||||
private HttpSessionEvent createHttpSessionEvent(AbstractSessionEvent event) {
|
||||
Session session = event.getSession();
|
||||
HttpSession httpSession = new HttpSessionAdapter<>(session,
|
||||
this.context);
|
||||
HttpSession httpSession = new HttpSessionAdapter<>(session, this.context);
|
||||
return new HttpSessionEvent(httpSession);
|
||||
}
|
||||
|
||||
@@ -91,4 +91,5 @@ public class SessionEventHttpSessionListenerAdapter
|
||||
public void setServletContext(ServletContext servletContext) {
|
||||
this.context = servletContext;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -79,25 +79,21 @@ import org.springframework.session.SessionRepository;
|
||||
@Order(SessionRepositoryFilter.DEFAULT_ORDER)
|
||||
public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFilter {
|
||||
|
||||
private static final String SESSION_LOGGER_NAME = SessionRepositoryFilter.class
|
||||
.getName().concat(".SESSION_LOGGER");
|
||||
private static final String SESSION_LOGGER_NAME = SessionRepositoryFilter.class.getName().concat(".SESSION_LOGGER");
|
||||
|
||||
private static final Log SESSION_LOGGER = LogFactory.getLog(SESSION_LOGGER_NAME);
|
||||
|
||||
/**
|
||||
* The session repository request attribute name.
|
||||
*/
|
||||
public static final String SESSION_REPOSITORY_ATTR = SessionRepository.class
|
||||
.getName();
|
||||
public static final String SESSION_REPOSITORY_ATTR = SessionRepository.class.getName();
|
||||
|
||||
/**
|
||||
* Invalid session id (not backed by the session repository) request attribute name.
|
||||
*/
|
||||
public static final String INVALID_SESSION_ID_ATTR = SESSION_REPOSITORY_ATTR
|
||||
+ ".invalidSessionId";
|
||||
public static final String INVALID_SESSION_ID_ATTR = SESSION_REPOSITORY_ATTR + ".invalidSessionId";
|
||||
|
||||
private static final String CURRENT_SESSION_ATTR = SESSION_REPOSITORY_ATTR
|
||||
+ ".CURRENT_SESSION";
|
||||
private static final String CURRENT_SESSION_ATTR = SESSION_REPOSITORY_ATTR + ".CURRENT_SESSION";
|
||||
|
||||
/**
|
||||
* The default filter order.
|
||||
@@ -110,7 +106,6 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param sessionRepository the <code>SessionRepository</code> to use. Cannot be null.
|
||||
*/
|
||||
public SessionRepositoryFilter(SessionRepository<S> sessionRepository) {
|
||||
@@ -123,7 +118,6 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
/**
|
||||
* Sets the {@link HttpSessionIdResolver} to be used. The default is a
|
||||
* {@link CookieHttpSessionIdResolver}.
|
||||
*
|
||||
* @param httpSessionIdResolver the {@link HttpSessionIdResolver} to use. Cannot be
|
||||
* null.
|
||||
*/
|
||||
@@ -135,15 +129,13 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain filterChain)
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
request.setAttribute(SESSION_REPOSITORY_ATTR, this.sessionRepository);
|
||||
|
||||
SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(
|
||||
request, response);
|
||||
SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(
|
||||
wrappedRequest, response);
|
||||
SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(request, response);
|
||||
SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(wrappedRequest,
|
||||
response);
|
||||
|
||||
try {
|
||||
filterChain.doFilter(wrappedRequest, wrappedResponse);
|
||||
@@ -159,8 +151,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
* @author Rob Winch
|
||||
* @since 1.0
|
||||
*/
|
||||
private final class SessionRepositoryResponseWrapper
|
||||
extends OnCommittedResponseWrapper {
|
||||
private final class SessionRepositoryResponseWrapper extends OnCommittedResponseWrapper {
|
||||
|
||||
private final SessionRepositoryRequestWrapper request;
|
||||
|
||||
@@ -169,8 +160,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
* @param request the request to be wrapped
|
||||
* @param response the response to be wrapped
|
||||
*/
|
||||
SessionRepositoryResponseWrapper(SessionRepositoryRequestWrapper request,
|
||||
HttpServletResponse response) {
|
||||
SessionRepositoryResponseWrapper(SessionRepositoryRequestWrapper request, HttpServletResponse response) {
|
||||
super(response);
|
||||
if (request == null) {
|
||||
throw new IllegalArgumentException("request cannot be null");
|
||||
@@ -182,6 +172,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
protected void onResponseCommitted() {
|
||||
this.request.commitSession();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,8 +183,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
* @author Rob Winch
|
||||
* @since 1.0
|
||||
*/
|
||||
private final class SessionRepositoryRequestWrapper
|
||||
extends HttpServletRequestWrapper {
|
||||
private final class SessionRepositoryRequestWrapper extends HttpServletRequestWrapper {
|
||||
|
||||
private final HttpServletResponse response;
|
||||
|
||||
@@ -207,8 +197,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
|
||||
private boolean requestedSessionInvalidated;
|
||||
|
||||
private SessionRepositoryRequestWrapper(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
private SessionRepositoryRequestWrapper(HttpServletRequest request, HttpServletResponse response) {
|
||||
super(request);
|
||||
this.response = response;
|
||||
}
|
||||
@@ -221,8 +210,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
HttpSessionWrapper wrappedSession = getCurrentSession();
|
||||
if (wrappedSession == null) {
|
||||
if (isInvalidateClientSession()) {
|
||||
SessionRepositoryFilter.this.httpSessionIdResolver.expireSession(this,
|
||||
this.response);
|
||||
SessionRepositoryFilter.this.httpSessionIdResolver.expireSession(this, this.response);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -230,10 +218,8 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
clearRequestedSessionCache();
|
||||
SessionRepositoryFilter.this.sessionRepository.save(session);
|
||||
String sessionId = session.getId();
|
||||
if (!isRequestedSessionIdValid()
|
||||
|| !sessionId.equals(getRequestedSessionId())) {
|
||||
SessionRepositoryFilter.this.httpSessionIdResolver.setSessionId(this,
|
||||
this.response, sessionId);
|
||||
if (!isRequestedSessionIdValid() || !sessionId.equals(getRequestedSessionId())) {
|
||||
SessionRepositoryFilter.this.httpSessionIdResolver.setSessionId(this, this.response, sessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -321,8 +307,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
SESSION_LOGGER.debug(
|
||||
"A new session was created. To help you troubleshoot where the session was created we provided a StackTrace (this is not an error). You can prevent this from appearing by disabling DEBUG logging for "
|
||||
+ SESSION_LOGGER_NAME,
|
||||
new RuntimeException(
|
||||
"For debugging purposes only (not an error)"));
|
||||
new RuntimeException("For debugging purposes only (not an error)"));
|
||||
}
|
||||
S session = SessionRepositoryFilter.this.sessionRepository.createSession();
|
||||
session.setLastAccessedTime(Instant.now());
|
||||
@@ -352,14 +337,12 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
|
||||
private S getRequestedSession() {
|
||||
if (!this.requestedSessionCached) {
|
||||
List<String> sessionIds = SessionRepositoryFilter.this.httpSessionIdResolver
|
||||
.resolveSessionIds(this);
|
||||
List<String> sessionIds = SessionRepositoryFilter.this.httpSessionIdResolver.resolveSessionIds(this);
|
||||
for (String sessionId : sessionIds) {
|
||||
if (this.requestedSessionId == null) {
|
||||
this.requestedSessionId = sessionId;
|
||||
}
|
||||
S session = SessionRepositoryFilter.this.sessionRepository
|
||||
.findById(sessionId);
|
||||
S session = SessionRepositoryFilter.this.sessionRepository.findById(sessionId);
|
||||
if (session != null) {
|
||||
this.requestedSession = session;
|
||||
this.requestedSessionId = sessionId;
|
||||
@@ -397,6 +380,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
clearRequestedSessionCache();
|
||||
SessionRepositoryFilter.this.sessionRepository.deleteById(getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -404,8 +388,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
*
|
||||
* @since 1.3.4
|
||||
*/
|
||||
private final class SessionCommittingRequestDispatcher
|
||||
implements RequestDispatcher {
|
||||
private final class SessionCommittingRequestDispatcher implements RequestDispatcher {
|
||||
|
||||
private final RequestDispatcher delegate;
|
||||
|
||||
@@ -414,14 +397,12 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forward(ServletRequest request, ServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException {
|
||||
this.delegate.forward(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void include(ServletRequest request, ServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException {
|
||||
SessionRepositoryRequestWrapper.this.commitSession();
|
||||
this.delegate.include(request, response);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -61,12 +61,14 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link Clock} to use to set lastAccessTime on every created
|
||||
* session and to calculate if it is expired.
|
||||
* <p>This may be useful to align to different timezone or to set the clock
|
||||
* back in a test, e.g. {@code Clock.offset(clock, Duration.ofMinutes(-31))}
|
||||
* in order to simulate session expiration.
|
||||
* <p>By default this is {@code Clock.system(ZoneId.of("GMT"))}.
|
||||
* Configure the {@link Clock} to use to set lastAccessTime on every created session
|
||||
* and to calculate if it is expired.
|
||||
* <p>
|
||||
* This may be useful to align to different timezone or to set the clock back in a
|
||||
* test, e.g. {@code Clock.offset(clock, Duration.ofMinutes(-31))} in order to
|
||||
* simulate session expiration.
|
||||
* <p>
|
||||
* By default this is {@code Clock.system(ZoneId.of("GMT"))}.
|
||||
* @param clock the clock to use
|
||||
*/
|
||||
public void setClock(Clock clock) {
|
||||
@@ -90,8 +92,7 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
|
||||
@Override
|
||||
public Mono<WebSession> retrieveSession(String sessionId) {
|
||||
return this.sessions.findById(sessionId)
|
||||
.doOnNext((session) -> session.setLastAccessedTime(this.clock.instant()))
|
||||
.map(this::existingSession);
|
||||
.doOnNext((session) -> session.setLastAccessedTime(this.clock.instant())).map(this::existingSession);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,8 +134,7 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
|
||||
@Override
|
||||
public Mono<Void> changeSessionId() {
|
||||
return Mono.defer(() -> {
|
||||
this.session
|
||||
.changeSessionId();
|
||||
this.session.changeSessionId();
|
||||
return save();
|
||||
});
|
||||
}
|
||||
@@ -152,8 +152,7 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
|
||||
@Override
|
||||
public boolean isStarted() {
|
||||
State value = this.state.get();
|
||||
return (State.STARTED.equals(value)
|
||||
|| (State.NEW.equals(value) && !getAttributes().isEmpty()));
|
||||
return (State.STARTED.equals(value) || (State.NEW.equals(value) && !getAttributes().isEmpty()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -198,10 +197,13 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
|
||||
public void setMaxIdleTime(Duration maxIdleTime) {
|
||||
this.session.setMaxInactiveInterval(maxIdleTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private enum State {
|
||||
|
||||
NEW, STARTED, EXPIRED
|
||||
|
||||
}
|
||||
|
||||
private static class SpringSessionMap implements Map<String, Object> {
|
||||
@@ -226,8 +228,7 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
return key instanceof String
|
||||
&& this.session.getAttributeNames().contains(key);
|
||||
return key instanceof String && this.session.getAttributeNames().contains(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -346,5 +347,7 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -93,8 +93,7 @@ public abstract class AbstractSessionWebSocketMessageBrokerConfigurer<S extends
|
||||
public final void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||
if (registry instanceof WebMvcStompEndpointRegistry) {
|
||||
WebMvcStompEndpointRegistry mvcRegistry = (WebMvcStompEndpointRegistry) registry;
|
||||
configureStompEndpoints(new SessionStompEndpointRegistry(mvcRegistry,
|
||||
sessionRepositoryInterceptor()));
|
||||
configureStompEndpoints(new SessionStompEndpointRegistry(mvcRegistry, sessionRepositoryInterceptor()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +101,6 @@ public abstract class AbstractSessionWebSocketMessageBrokerConfigurer<S extends
|
||||
* Register STOMP endpoints mapping each to a specific URL and (optionally) enabling
|
||||
* and configuring SockJS fallback options with a
|
||||
* {@link SessionRepositoryMessageInterceptor} automatically added as an interceptor.
|
||||
*
|
||||
* @param registry the {@link StompEndpointRegistry} which automatically has a
|
||||
* {@link SessionRepositoryMessageInterceptor} added to it.
|
||||
*/
|
||||
@@ -133,19 +131,19 @@ public abstract class AbstractSessionWebSocketMessageBrokerConfigurer<S extends
|
||||
* A {@link StompEndpointRegistry} that applies {@link HandshakeInterceptor}.
|
||||
*/
|
||||
static class SessionStompEndpointRegistry implements StompEndpointRegistry {
|
||||
|
||||
private final WebMvcStompEndpointRegistry registry;
|
||||
|
||||
private final HandshakeInterceptor interceptor;
|
||||
|
||||
SessionStompEndpointRegistry(WebMvcStompEndpointRegistry registry,
|
||||
HandshakeInterceptor interceptor) {
|
||||
SessionStompEndpointRegistry(WebMvcStompEndpointRegistry registry, HandshakeInterceptor interceptor) {
|
||||
this.registry = registry;
|
||||
this.interceptor = interceptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StompWebSocketEndpointRegistration addEndpoint(String... paths) {
|
||||
StompWebSocketEndpointRegistration endpoints = this.registry
|
||||
.addEndpoint(paths);
|
||||
StompWebSocketEndpointRegistration endpoints = this.registry.addEndpoint(paths);
|
||||
endpoints.addInterceptors(this.interceptor);
|
||||
return endpoints;
|
||||
}
|
||||
@@ -161,9 +159,10 @@ public abstract class AbstractSessionWebSocketMessageBrokerConfigurer<S extends
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebMvcStompEndpointRegistry setErrorHandler(
|
||||
StompSubProtocolErrorHandler errorHandler) {
|
||||
public WebMvcStompEndpointRegistry setErrorHandler(StompSubProtocolErrorHandler errorHandler) {
|
||||
return this.registry.setErrorHandler(errorHandler);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -44,4 +44,5 @@ public class SessionConnectEvent extends ApplicationEvent {
|
||||
public WebSocketSession getWebSocketSession() {
|
||||
return this.webSocketSession;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -38,24 +38,19 @@ import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory;
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 1.0
|
||||
*
|
||||
* @see WebSocketRegistryListener
|
||||
*/
|
||||
public final class WebSocketConnectHandlerDecoratorFactory
|
||||
implements WebSocketHandlerDecoratorFactory {
|
||||
public final class WebSocketConnectHandlerDecoratorFactory implements WebSocketHandlerDecoratorFactory {
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(WebSocketConnectHandlerDecoratorFactory.class);
|
||||
private static final Log logger = LogFactory.getLog(WebSocketConnectHandlerDecoratorFactory.class);
|
||||
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param eventPublisher the {@link ApplicationEventPublisher} to use. Cannot be null.
|
||||
*/
|
||||
public WebSocketConnectHandlerDecoratorFactory(
|
||||
ApplicationEventPublisher eventPublisher) {
|
||||
public WebSocketConnectHandlerDecoratorFactory(ApplicationEventPublisher eventPublisher) {
|
||||
Assert.notNull(eventPublisher, "eventPublisher cannot be null");
|
||||
this.eventPublisher = eventPublisher;
|
||||
}
|
||||
@@ -72,8 +67,7 @@ public final class WebSocketConnectHandlerDecoratorFactory
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConnectionEstablished(WebSocketSession wsSession)
|
||||
throws Exception {
|
||||
public void afterConnectionEstablished(WebSocketSession wsSession) throws Exception {
|
||||
super.afterConnectionEstablished(wsSession);
|
||||
|
||||
publishEvent(new SessionConnectEvent(this, wsSession));
|
||||
@@ -81,12 +75,13 @@ public final class WebSocketConnectHandlerDecoratorFactory
|
||||
|
||||
private void publishEvent(ApplicationEvent event) {
|
||||
try {
|
||||
WebSocketConnectHandlerDecoratorFactory.this.eventPublisher
|
||||
.publishEvent(event);
|
||||
WebSocketConnectHandlerDecoratorFactory.this.eventPublisher.publishEvent(event);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.error("Error publishing " + event + ".", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -41,18 +41,15 @@ import org.springframework.web.socket.messaging.SessionDisconnectEvent;
|
||||
* {@link WebSocketSession} is closed.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Mark Anderson
|
||||
* @since 1.0
|
||||
*/
|
||||
public final class WebSocketRegistryListener
|
||||
implements ApplicationListener<ApplicationEvent> {
|
||||
public final class WebSocketRegistryListener implements ApplicationListener<ApplicationEvent> {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(WebSocketRegistryListener.class);
|
||||
|
||||
static final CloseStatus SESSION_EXPIRED_STATUS = new CloseStatus(
|
||||
CloseStatus.POLICY_VIOLATION.getCode(),
|
||||
static final CloseStatus SESSION_EXPIRED_STATUS = new CloseStatus(CloseStatus.POLICY_VIOLATION.getCode(),
|
||||
"This connection was established under an authenticated HTTP Session that has expired");
|
||||
|
||||
private final ConcurrentHashMap<String, Map<String, WebSocketSession>> httpSessionIdToWsSessions = new ConcurrentHashMap<>();
|
||||
@@ -72,8 +69,7 @@ public final class WebSocketRegistryListener
|
||||
Map<String, Object> sessionAttributes = SimpMessageHeaderAccessor
|
||||
.getSessionAttributes(e.getMessage().getHeaders());
|
||||
String httpSessionId = (sessionAttributes != null)
|
||||
? SessionRepositoryMessageInterceptor.getSessionId(sessionAttributes)
|
||||
: null;
|
||||
? SessionRepositoryMessageInterceptor.getSessionId(sessionAttributes) : null;
|
||||
afterConnectionClosed(httpSessionId, e.getSessionId());
|
||||
}
|
||||
}
|
||||
@@ -98,8 +94,7 @@ public final class WebSocketRegistryListener
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, WebSocketSession> sessions = this.httpSessionIdToWsSessions
|
||||
.get(httpSessionId);
|
||||
Map<String, WebSocketSession> sessions = this.httpSessionIdToWsSessions.get(httpSessionId);
|
||||
if (sessions != null) {
|
||||
boolean result = sessions.remove(wsSessionId) != null;
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -108,16 +103,15 @@ public final class WebSocketRegistryListener
|
||||
if (sessions.isEmpty()) {
|
||||
this.httpSessionIdToWsSessions.remove(httpSessionId);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Removed the corresponding HTTP Session for "
|
||||
+ wsSessionId + " since it contained no WebSocket mappings");
|
||||
logger.debug("Removed the corresponding HTTP Session for " + wsSessionId
|
||||
+ " since it contained no WebSocket mappings");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void registerWsSession(String httpSessionId, WebSocketSession wsSession) {
|
||||
Map<String, WebSocketSession> sessions = this.httpSessionIdToWsSessions
|
||||
.get(httpSessionId);
|
||||
Map<String, WebSocketSession> sessions = this.httpSessionIdToWsSessions.get(httpSessionId);
|
||||
if (sessions == null) {
|
||||
sessions = new ConcurrentHashMap<>();
|
||||
this.httpSessionIdToWsSessions.putIfAbsent(httpSessionId, sessions);
|
||||
@@ -127,25 +121,22 @@ public final class WebSocketRegistryListener
|
||||
}
|
||||
|
||||
private void closeWsSessions(String httpSessionId) {
|
||||
Map<String, WebSocketSession> sessionsToClose = this.httpSessionIdToWsSessions
|
||||
.remove(httpSessionId);
|
||||
Map<String, WebSocketSession> sessionsToClose = this.httpSessionIdToWsSessions.remove(httpSessionId);
|
||||
if (sessionsToClose == null) {
|
||||
return;
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
"Closing WebSocket connections associated to expired HTTP Session "
|
||||
+ httpSessionId);
|
||||
logger.debug("Closing WebSocket connections associated to expired HTTP Session " + httpSessionId);
|
||||
}
|
||||
for (WebSocketSession toClose : sessionsToClose.values()) {
|
||||
try {
|
||||
toClose.close(SESSION_EXPIRED_STATUS);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
logger.debug(
|
||||
"Failed to close WebSocketSession (this is nothing to worry about but for debugging only)",
|
||||
logger.debug("Failed to close WebSocketSession (this is nothing to worry about but for debugging only)",
|
||||
ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2019 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.
|
||||
@@ -72,15 +72,13 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param sessionRepository the {@link SessionRepository} to use. Cannot be null.
|
||||
*/
|
||||
public SessionRepositoryMessageInterceptor(SessionRepository<S> sessionRepository) {
|
||||
Assert.notNull(sessionRepository, "sessionRepository cannot be null");
|
||||
this.sessionRepository = sessionRepository;
|
||||
this.matchingMessageTypes = EnumSet.of(SimpMessageType.CONNECT,
|
||||
SimpMessageType.MESSAGE, SimpMessageType.SUBSCRIBE,
|
||||
SimpMessageType.UNSUBSCRIBE);
|
||||
this.matchingMessageTypes = EnumSet.of(SimpMessageType.CONNECT, SimpMessageType.MESSAGE,
|
||||
SimpMessageType.SUBSCRIBE, SimpMessageType.UNSUBSCRIBE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,14 +92,12 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
|
||||
* The default is: SimpMessageType.CONNECT, SimpMessageType.MESSAGE,
|
||||
* SimpMessageType.SUBSCRIBE, SimpMessageType.UNSUBSCRIBE.
|
||||
* </p>
|
||||
*
|
||||
* @param matchingMessageTypes the {@link SimpMessageType} to match on in
|
||||
* {@link #preSend(Message, MessageChannel)}, else the {@link Message} is continued
|
||||
* without accessing or updating the {@link Session}
|
||||
*/
|
||||
public void setMatchingMessageTypes(Set<SimpMessageType> matchingMessageTypes) {
|
||||
Assert.notEmpty(matchingMessageTypes,
|
||||
"matchingMessageTypes cannot be null or empty");
|
||||
Assert.notEmpty(matchingMessageTypes, "matchingMessageTypes cannot be null or empty");
|
||||
this.matchingMessageTypes = matchingMessageTypes;
|
||||
}
|
||||
|
||||
@@ -110,16 +106,12 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
|
||||
if (message == null) {
|
||||
return message;
|
||||
}
|
||||
SimpMessageType messageType = SimpMessageHeaderAccessor
|
||||
.getMessageType(message.getHeaders());
|
||||
SimpMessageType messageType = SimpMessageHeaderAccessor.getMessageType(message.getHeaders());
|
||||
if (!this.matchingMessageTypes.contains(messageType)) {
|
||||
return message;
|
||||
}
|
||||
Map<String, Object> sessionHeaders = SimpMessageHeaderAccessor
|
||||
.getSessionAttributes(message.getHeaders());
|
||||
String sessionId = (sessionHeaders != null)
|
||||
? (String) sessionHeaders.get(SPRING_SESSION_ID_ATTR_NAME)
|
||||
: null;
|
||||
Map<String, Object> sessionHeaders = SimpMessageHeaderAccessor.getSessionAttributes(message.getHeaders());
|
||||
String sessionId = (sessionHeaders != null) ? (String) sessionHeaders.get(SPRING_SESSION_ID_ATTR_NAME) : null;
|
||||
if (sessionId != null) {
|
||||
S session = this.sessionRepository.findById(sessionId);
|
||||
if (session != null) {
|
||||
@@ -132,8 +124,8 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
|
||||
WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
|
||||
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
|
||||
Map<String, Object> attributes) throws Exception {
|
||||
if (request instanceof ServletServerHttpRequest) {
|
||||
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
|
||||
HttpSession session = servletRequest.getServletRequest().getSession(false);
|
||||
@@ -145,8 +137,8 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,
|
||||
WebSocketHandler wsHandler, Exception exception) {
|
||||
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
|
||||
Exception exception) {
|
||||
}
|
||||
|
||||
public static String getSessionId(Map<String, Object> attributes) {
|
||||
@@ -156,4 +148,5 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
|
||||
public static void setSessionId(Map<String, Object> attributes, String sessionId) {
|
||||
attributes.put(SPRING_SESSION_ID_ATTR_NAME, sessionId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user