Create ExpiringSession which extends Session
This provides a better separation for consumers of the API. Most users are likely not interested in checking to see if a session is expired so they can focus on the Session API. Fixes #28
This commit is contained in:
@@ -189,8 +189,8 @@ public class Config {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<String,Session> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
RedisTemplate<String, Session> template = new RedisTemplate<String, Session>();
|
||||
public RedisTemplate<String,ExpiringSession> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
RedisTemplate<String, ExpiringSession> template = new RedisTemplate<String, ExpiringSession>();
|
||||
template.setKeySerializer(new StringRedisSerializer());
|
||||
template.setHashKeySerializer(new StringRedisSerializer());
|
||||
template.setConnectionFactory(connectionFactory);
|
||||
@@ -198,7 +198,7 @@ public class Config {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisOperationsSessionRepository sessionRepository(RedisTemplate<String, Session> redisTemplate) {
|
||||
public RedisOperationsSessionRepository sessionRepository(RedisTemplate<String, ExpiringSession> redisTemplate) {
|
||||
return new RedisOperationsSessionRepository(redisTemplate);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
import org.springframework.session.ExpiringSession;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
|
||||
import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
@@ -72,7 +73,7 @@ public class Config {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisOperationsSessionRepository sessionRepository(RedisTemplate<String, Session> redisTemplate) {
|
||||
public RedisOperationsSessionRepository sessionRepository(RedisTemplate<String, ExpiringSession> redisTemplate) {
|
||||
return new RedisOperationsSessionRepository(redisTemplate);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.session.ExpiringSession;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
@@ -100,8 +101,8 @@ public class RedisOperationsSessionRepositoryITests {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<String,Session> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
RedisTemplate<String, Session> template = new RedisTemplate<String, Session>();
|
||||
public RedisTemplate<String,ExpiringSession> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
RedisTemplate<String, ExpiringSession> template = new RedisTemplate<String, ExpiringSession>();
|
||||
template.setKeySerializer(new StringRedisSerializer());
|
||||
template.setHashKeySerializer(new StringRedisSerializer());
|
||||
template.setConnectionFactory(connectionFactory);
|
||||
@@ -109,7 +110,7 @@ public class RedisOperationsSessionRepositoryITests {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisOperationsSessionRepository sessionRepository(RedisTemplate<String, Session> redisTemplate) {
|
||||
public RedisOperationsSessionRepository sessionRepository(RedisTemplate<String, ExpiringSession> redisTemplate) {
|
||||
return new RedisOperationsSessionRepository(redisTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.springframework.session;
|
||||
|
||||
/**
|
||||
* A {@link Session} that contains additional attributes that are useful for determining if a session is expired.
|
||||
*
|
||||
* @since 1.0
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public interface ExpiringSession extends Session {
|
||||
|
||||
/**
|
||||
* Gets the time when this session was created in milliseconds since midnight of 1/1/1970 GMT.
|
||||
*
|
||||
* @return the time when this session was created in milliseconds since midnight of 1/1/1970 GMT.
|
||||
*/
|
||||
long getCreationTime();
|
||||
|
||||
/**
|
||||
* Gets the last time this {@link Session} was accessed expressed in milliseconds since midnight of 1/1/1970 GMT
|
||||
*
|
||||
* @return the last time the client sent a request associated with the session expressed in milliseconds since midnight of 1/1/1970 GMT
|
||||
*/
|
||||
long getLastAccessedTime();
|
||||
|
||||
/**
|
||||
* Sets the maximum inactive interval in seconds between requests before this session will be invalidated. A negative time indicates that the session will never timeout.
|
||||
*
|
||||
* @param interval the number of seconds that the {@link Session} should be kept alive between client requests.
|
||||
*/
|
||||
void setMaxInactiveInterval(int interval);
|
||||
|
||||
/**
|
||||
* Gets the maximum inactive interval in seconds between requests before this session will be invalidated. A negative time indicates that the session will never timeout.
|
||||
*
|
||||
* @return the maximum inactive interval in seconds between requests before this session will be invalidated. A negative time indicates that the session will never timeout.
|
||||
*/
|
||||
int getMaxInactiveInterval();
|
||||
|
||||
}
|
||||
@@ -40,7 +40,7 @@ import java.util.UUID;
|
||||
* @since 1.0
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public final class MapSession implements Session {
|
||||
public final class MapSession implements ExpiringSession {
|
||||
/**
|
||||
* Default {@link #setMaxInactiveInterval(int)} (30 minutes)
|
||||
*/
|
||||
@@ -67,7 +67,7 @@ public final class MapSession implements Session {
|
||||
*
|
||||
* @param session the {@link Session} to initialize this {@link Session} with. Cannot be null.
|
||||
*/
|
||||
public MapSession(Session session) {
|
||||
public MapSession(ExpiringSession session) {
|
||||
Assert.notNull(session, "session cannot be null");
|
||||
this.id = session.getId();
|
||||
this.sessionAttrs = new HashMap<String, Object>(session.getAttributeNames().size());
|
||||
|
||||
@@ -28,14 +28,14 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* @author Rob Winch
|
||||
* @since 1.0
|
||||
*/
|
||||
public class MapSessionRepository implements SessionRepository<Session> {
|
||||
private final Map<String,Session> sessions;
|
||||
public class MapSessionRepository implements SessionRepository<ExpiringSession> {
|
||||
private final Map<String,ExpiringSession> sessions;
|
||||
|
||||
/**
|
||||
* Creates an instance backed by a {@link java.util.concurrent.ConcurrentHashMap}
|
||||
*/
|
||||
public MapSessionRepository() {
|
||||
this(new ConcurrentHashMap<String, Session>());
|
||||
this(new ConcurrentHashMap<String, ExpiringSession>());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,17 +43,17 @@ public class MapSessionRepository implements SessionRepository<Session> {
|
||||
*
|
||||
* @param sessions the {@link java.util.Map} to use. Cannot be null.
|
||||
*/
|
||||
public MapSessionRepository(Map<String,Session> sessions) {
|
||||
public MapSessionRepository(Map<String,ExpiringSession> sessions) {
|
||||
Assert.notNull(sessions, "sessions cannot be null");
|
||||
this.sessions = sessions;
|
||||
}
|
||||
|
||||
public void save(Session session) {
|
||||
public void save(ExpiringSession session) {
|
||||
sessions.put(session.getId(), new MapSession(session));
|
||||
}
|
||||
|
||||
public Session getSession(String id) {
|
||||
Session saved = sessions.get(id);
|
||||
public ExpiringSession getSession(String id) {
|
||||
ExpiringSession saved = sessions.get(id);
|
||||
if(saved == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -66,7 +66,7 @@ public class MapSessionRepository implements SessionRepository<Session> {
|
||||
sessions.remove(id);
|
||||
}
|
||||
|
||||
public Session createSession() {
|
||||
public ExpiringSession createSession() {
|
||||
return new MapSession();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,13 +27,6 @@ import java.util.Set;
|
||||
*/
|
||||
public interface Session {
|
||||
|
||||
/**
|
||||
* Gets the time when this session was created in milliseconds since midnight of 1/1/1970 GMT.
|
||||
*
|
||||
* @return the time when this session was created in milliseconds since midnight of 1/1/1970 GMT.
|
||||
*/
|
||||
long getCreationTime();
|
||||
|
||||
/**
|
||||
* Gets a unique string that identifies the {@link Session}
|
||||
*
|
||||
@@ -41,27 +34,6 @@ public interface Session {
|
||||
*/
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* Gets the last time this {@link Session} was accessed expressed in milliseconds since midnight of 1/1/1970 GMT
|
||||
*
|
||||
* @return the last time the client sent a request associated with the session expressed in milliseconds since midnight of 1/1/1970 GMT
|
||||
*/
|
||||
long getLastAccessedTime();
|
||||
|
||||
/**
|
||||
* Sets the maximum inactive interval in seconds between requests before this session will be invalidated. A negative time indicates that the session will never timeout.
|
||||
*
|
||||
* @param interval the number of seconds that the {@link Session} should be kept alive between client requests.
|
||||
*/
|
||||
void setMaxInactiveInterval(int interval);
|
||||
|
||||
/**
|
||||
* Gets the maximum inactive interval in seconds between requests before this session will be invalidated. A negative time indicates that the session will never timeout.
|
||||
*
|
||||
* @return the maximum inactive interval in seconds between requests before this session will be invalidated. A negative time indicates that the session will never timeout.
|
||||
*/
|
||||
int getMaxInactiveInterval();
|
||||
|
||||
/**
|
||||
* Gets the Object associated with the specified name or null if no Object is associated to that name.
|
||||
*
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.session.data.redis;
|
||||
|
||||
import org.springframework.data.redis.core.BoundHashOperations;
|
||||
import org.springframework.data.redis.core.RedisOperations;
|
||||
import org.springframework.session.ExpiringSession;
|
||||
import org.springframework.session.MapSession;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.SessionRepository;
|
||||
@@ -99,17 +100,17 @@ public class RedisOperationsSessionRepository implements SessionRepository<Redis
|
||||
static final String BOUNDED_HASH_KEY_PREFIX = "spring-security-sessions:";
|
||||
|
||||
/**
|
||||
* The key in the Hash representing {@link org.springframework.session.Session#getCreationTime()}
|
||||
* The key in the Hash representing {@link org.springframework.session.ExpiringSession#getCreationTime()}
|
||||
*/
|
||||
static final String CREATION_TIME_ATTR = "creationTime";
|
||||
|
||||
/**
|
||||
* The key in the Hash representing {@link org.springframework.session.Session#getMaxInactiveInterval()}
|
||||
* The key in the Hash representing {@link org.springframework.session.ExpiringSession#getMaxInactiveInterval()}
|
||||
*/
|
||||
static final String MAX_INACTIVE_ATTR = "maxInactiveInterval";
|
||||
|
||||
/**
|
||||
* The key in the Hash representing {@link org.springframework.session.Session#getLastAccessedTime()}
|
||||
* The key in the Hash representing {@link org.springframework.session.ExpiringSession#getLastAccessedTime()}
|
||||
*/
|
||||
static final String LAST_ACCESSED_ATTR = "lastAccessedTime";
|
||||
|
||||
@@ -120,7 +121,7 @@ public class RedisOperationsSessionRepository implements SessionRepository<Redis
|
||||
*/
|
||||
static final String SESSION_ATTR_PREFIX = "sessionAttr:";
|
||||
|
||||
private final RedisOperations<String,Session> redisOperations;
|
||||
private final RedisOperations<String,ExpiringSession> redisOperations;
|
||||
|
||||
/**
|
||||
* If non-null, this value is used to override {@link RedisSession#setDefaultMaxInactiveInterval(int)}.
|
||||
@@ -132,7 +133,7 @@ public class RedisOperationsSessionRepository implements SessionRepository<Redis
|
||||
*
|
||||
* @param redisOperations The {@link RedisOperations} to use. Cannot be null.
|
||||
*/
|
||||
public RedisOperationsSessionRepository(RedisOperations<String, Session> redisOperations) {
|
||||
public RedisOperationsSessionRepository(RedisOperations<String, ExpiringSession> redisOperations) {
|
||||
Assert.notNull(redisOperations, "RedisOperations cannot be null");
|
||||
this.redisOperations = redisOperations;
|
||||
}
|
||||
@@ -232,7 +233,7 @@ public class RedisOperationsSessionRepository implements SessionRepository<Redis
|
||||
* @since 1.0
|
||||
* @author Rob Winch
|
||||
*/
|
||||
final class RedisSession implements Session {
|
||||
final class RedisSession implements ExpiringSession {
|
||||
private final MapSession cached;
|
||||
private Map<String, Object> delta = new HashMap<String,Object>();
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.springframework.session.web.http;
|
||||
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.ExpiringSession;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -43,15 +43,14 @@ import java.util.Set;
|
||||
* <ul>
|
||||
* <li>The session id is looked up using {@link HttpSessionStrategy#getRequestedSessionId(javax.servlet.http.HttpServletRequest)}.
|
||||
* The default is to look in a cookie named SESSION.</li>
|
||||
* <li>The session id of newly created {@link org.springframework.session.Session} is sent to the client using
|
||||
* {@link HttpSessionStrategy#onNewSession(org.springframework.session.Session, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)} </li>
|
||||
* <li>The session id of newly created {@link org.springframework.session.ExpiringSession} is sent to the client using
|
||||
* <li>The client is notified that the session id is no longer valid with {@link HttpSessionStrategy#onInvalidateSession(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @since 1.0
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFilter {
|
||||
public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerRequestFilter {
|
||||
private final SessionRepository<S> sessionRepository;
|
||||
|
||||
private HttpSessionStrategy httpSessionStrategy = new CookieHttpSessionStrategy();
|
||||
|
||||
@@ -50,7 +50,7 @@ public class MapSessionTests {
|
||||
assertThat(session.hashCode()).isEqualTo(session.getId().hashCode());
|
||||
}
|
||||
|
||||
static class CustomSession implements Session {
|
||||
static class CustomSession implements ExpiringSession {
|
||||
|
||||
@Override
|
||||
public long getCreationTime() {
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.redis.core.BoundHashOperations;
|
||||
import org.springframework.data.redis.core.RedisOperations;
|
||||
import org.springframework.session.ExpiringSession;
|
||||
import org.springframework.session.MapSession;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.data.redis.RedisOperationsSessionRepository.RedisSession;
|
||||
@@ -25,7 +26,7 @@ import org.springframework.session.data.redis.RedisOperationsSessionRepository.R
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class RedisOperationsSessionRepositoryTests {
|
||||
@Mock
|
||||
RedisOperations<String,Session> redisOperations;
|
||||
RedisOperations<String,ExpiringSession> redisOperations;
|
||||
@Mock
|
||||
BoundHashOperations<String, Object, Object> boundHashOperations;
|
||||
@Captor
|
||||
@@ -40,7 +41,7 @@ public class RedisOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
public void createSessionDefaultMaxInactiveInterval() throws Exception {
|
||||
Session session = redisRepository.createSession();
|
||||
ExpiringSession session = redisRepository.createSession();
|
||||
assertThat(session.getMaxInactiveInterval()).isEqualTo(new MapSession().getMaxInactiveInterval());
|
||||
}
|
||||
|
||||
@@ -48,7 +49,7 @@ public class RedisOperationsSessionRepositoryTests {
|
||||
public void createSessionCustomMaxInactiveInterval() throws Exception {
|
||||
int interval = 1;
|
||||
redisRepository.setDefaultMaxInactiveInterval(interval);
|
||||
Session session = redisRepository.createSession();
|
||||
ExpiringSession session = redisRepository.createSession();
|
||||
assertThat(session.getMaxInactiveInterval()).isEqualTo(interval);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user