Add Session.changeSessionId

This commit is contained in:
Rob Winch
2017-07-20 15:03:18 -05:00
parent 2aa71ffb6d
commit be2604ca69
29 changed files with 576 additions and 169 deletions

View File

@@ -50,7 +50,7 @@ public class IndexDocTests {
@Test
public void repositoryDemo() {
RepositoryDemo<Session> demo = new RepositoryDemo<>();
RepositoryDemo<MapSession> demo = new RepositoryDemo<>();
demo.repository = new MapSessionRepository();
demo.demo();
@@ -82,7 +82,7 @@ public class IndexDocTests {
@Test
public void expireRepositoryDemo() {
ExpiringRepositoryDemo<Session> demo = new ExpiringRepositoryDemo<>();
ExpiringRepositoryDemo<MapSession> demo = new ExpiringRepositoryDemo<>();
demo.repository = new MapSessionRepository();
demo.demo();

View File

@@ -34,7 +34,6 @@ import com.hazelcast.core.HazelcastInstance;
import org.springframework.session.MapSession;
import org.springframework.session.MapSessionRepository;
import org.springframework.session.Session;
import org.springframework.session.SessionRepository;
import org.springframework.session.web.http.SessionRepositoryFilter;
@WebListener
@@ -48,8 +47,8 @@ public class Initializer implements ServletContextListener {
this.instance = createHazelcastInstance();
Map<String, Session> sessions = this.instance.getMap(SESSION_MAP_NAME);
SessionRepository<Session> sessionRepository = new MapSessionRepository(sessions);
SessionRepositoryFilter<Session> filter = new SessionRepositoryFilter<>(
MapSessionRepository sessionRepository = new MapSessionRepository(sessions);
SessionRepositoryFilter<? extends Session> filter = new SessionRepositoryFilter<>(
sessionRepository);
Dynamic fr = sce.getServletContext().addFilter("springSessionFilter", filter);

View File

@@ -39,7 +39,7 @@ import org.springframework.session.events.SessionExpiredEvent;
* @author Rob Winch
* @since 2.0
*/
public class MapReactorSessionRepository implements ReactorSessionRepository<Session> {
public class MapReactorSessionRepository implements ReactorSessionRepository<MapSession> {
/**
* If non-null, this value is used to override
* {@link Session#setMaxInactiveInterval(Duration)}.
@@ -80,7 +80,7 @@ public class MapReactorSessionRepository implements ReactorSessionRepository<Ses
}
this.sessions = new ConcurrentHashMap<>();
for (Session session : sessions) {
this.performSave(session);
this.performSave(new MapSession(session));
}
}
@@ -96,7 +96,7 @@ public class MapReactorSessionRepository implements ReactorSessionRepository<Ses
}
this.sessions = new ConcurrentHashMap<>();
for (Session session : sessions) {
this.performSave(session);
this.performSave(new MapSession(session));
}
}
@@ -110,15 +110,19 @@ public class MapReactorSessionRepository implements ReactorSessionRepository<Ses
this.defaultMaxInactiveInterval = Integer.valueOf(defaultMaxInactiveInterval);
}
public Mono<Void> save(Session session) {
public Mono<Void> save(MapSession session) {
return Mono.fromRunnable(() -> performSave(session));
}
private void performSave(Session session) {
private void performSave(MapSession session) {
if (!session.getId().equals(session.getOriginalId())) {
this.sessions.remove(session.getOriginalId());
session.setOriginalId(session.getId());
}
this.sessions.put(session.getId(), new MapSession(session));
}
public Mono<Session> findById(String id) {
public Mono<MapSession> findById(String id) {
return Mono.defer(() -> {
Session saved = this.sessions.get(id);
if (saved == null) {
@@ -136,9 +140,9 @@ public class MapReactorSessionRepository implements ReactorSessionRepository<Ses
return Mono.fromRunnable(() -> this.sessions.remove(id));
}
public Mono<Session> createSession() {
public Mono<MapSession> createSession() {
return Mono.defer(() -> {
Session result = new MapSession();
MapSession result = new MapSession();
if (this.defaultMaxInactiveInterval != null) {
result.setMaxInactiveInterval(
Duration.ofSeconds(this.defaultMaxInactiveInterval));

View File

@@ -52,6 +52,7 @@ public final class MapSession implements Session, Serializable {
public static final int DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS = 1800;
private String id;
private String originalId;
private Map<String, Object> sessionAttrs = new HashMap<>();
private Instant creationTime = Instant.now();
private Instant lastAccessedTime = this.creationTime;
@@ -65,9 +66,10 @@ public final class MapSession implements Session, Serializable {
* Creates a new instance with a secure randomly generated identifier.
*/
public MapSession() {
this(UUID.randomUUID().toString());
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
@@ -77,6 +79,7 @@ public final class MapSession implements Session, Serializable {
*/
public MapSession(String id) {
this.id = id;
this.originalId = id;
}
/**
@@ -90,6 +93,7 @@ public final class MapSession implements Session, Serializable {
throw new IllegalArgumentException("session cannot be null");
}
this.id = session.getId();
this.originalId = this.id;
this.sessionAttrs = new HashMap<>(
session.getAttributeNames().size());
for (String attrName : session.getAttributeNames()) {
@@ -115,6 +119,20 @@ public final class MapSession implements Session, Serializable {
return this.id;
}
String getOriginalId() {
return this.originalId;
}
void setOriginalId(String originalId) {
this.originalId = originalId;
}
public String changeSessionId() {
String changedId = generateId();
setId(changedId);
return changedId;
}
public Instant getLastAccessedTime() {
return this.lastAccessedTime;
}
@@ -188,5 +206,9 @@ public final class MapSession implements Session, Serializable {
return this.id.hashCode();
}
private static String generateId() {
return UUID.randomUUID().toString();
}
private static final long serialVersionUID = 7160779239673823561L;
}

View File

@@ -37,7 +37,7 @@ import org.springframework.session.events.SessionExpiredEvent;
* @author Rob Winch
* @since 1.0
*/
public class MapSessionRepository implements SessionRepository<Session> {
public class MapSessionRepository implements SessionRepository<MapSession> {
/**
* If non-null, this value is used to override
* {@link Session#setMaxInactiveInterval(Duration)}.
@@ -76,11 +76,15 @@ public class MapSessionRepository implements SessionRepository<Session> {
this.defaultMaxInactiveInterval = Integer.valueOf(defaultMaxInactiveInterval);
}
public void save(Session session) {
public void save(MapSession session) {
if (!session.getId().equals(session.getOriginalId())) {
this.sessions.remove(session.getOriginalId());
session.setOriginalId(session.getId());
}
this.sessions.put(session.getId(), new MapSession(session));
}
public Session findById(String id) {
public MapSession findById(String id) {
Session saved = this.sessions.get(id);
if (saved == null) {
return null;
@@ -96,8 +100,8 @@ public class MapSessionRepository implements SessionRepository<Session> {
this.sessions.remove(id);
}
public Session createSession() {
Session result = new MapSession();
public MapSession createSession() {
MapSession result = new MapSession();
if (this.defaultMaxInactiveInterval != null) {
result.setMaxInactiveInterval(
Duration.ofSeconds(this.defaultMaxInactiveInterval));

View File

@@ -37,6 +37,12 @@ public interface Session {
*/
String getId();
/**
* 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();
/**
* Gets the Object associated with the specified name or null if no Object is
* associated to that name.

View File

@@ -18,9 +18,6 @@ package org.springframework.session.web.http;
import java.io.IOException;
import java.time.Instant;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.FilterChain;
import javax.servlet.ServletContext;
@@ -274,30 +271,7 @@ public class SessionRepositoryFilter<S extends Session>
"Cannot change session ID. There is no session associated with this request.");
}
// eagerly get session attributes in case implementation lazily loads them
Map<String, Object> attrs = new HashMap<>();
Enumeration<String> iAttrNames = session.getAttributeNames();
while (iAttrNames.hasMoreElements()) {
String attrName = iAttrNames.nextElement();
Object value = session.getAttribute(attrName);
attrs.put(attrName, value);
}
SessionRepositoryFilter.this.sessionRepository.deleteById(session.getId());
HttpSessionWrapper original = getCurrentSession();
setCurrentSession(null);
HttpSessionWrapper newSession = getSession();
original.setSession(newSession.getSession());
newSession.setMaxInactiveInterval(session.getMaxInactiveInterval());
for (Map.Entry<String, Object> attr : attrs.entrySet()) {
String attrName = attr.getKey();
Object attrValue = attr.getValue();
newSession.setAttribute(attrName, attrValue);
}
return newSession.getId();
return getCurrentSession().getSession().changeSessionId();
}
@Override

View File

@@ -145,4 +145,32 @@ public class MapReactorSessionRepositoryTests {
assertThat(session.getMaxInactiveInterval())
.isEqualTo(expectedMaxInterval);
}
@Test
public void changeSessionIdWhenNotYetSaved() {
MapSession createSession = this.repository.createSession().block();
String originalId = createSession.getId();
createSession.changeSessionId();
this.repository.save(createSession).block();
assertThat(this.repository.findById(originalId).block()).isNull();
assertThat(this.repository.findById(createSession.getId()).block()).isNotNull();
}
@Test
public void changeSessionIdWhenSaved() {
MapSession createSession = this.repository.createSession().block();
this.repository.save(createSession).block();
String originalId = createSession.getId();
createSession.changeSessionId();
this.repository.save(createSession).block();
assertThat(this.repository.findById(originalId).block()).isNull();
assertThat(this.repository.findById(createSession.getId()).block()).isNotNull();
}
}

View File

@@ -66,4 +66,32 @@ public class MapSessionRepositoryTests {
assertThat(session.getMaxInactiveInterval())
.isEqualTo(expectedMaxInterval);
}
@Test
public void changeSessionIdWhenNotYetSaved() {
MapSession createSession = this.repository.createSession();
String originalId = createSession.getId();
createSession.changeSessionId();
this.repository.save(createSession);
assertThat(this.repository.findById(originalId)).isNull();
assertThat(this.repository.findById(createSession.getId())).isNotNull();
}
@Test
public void changeSessionIdWhenSaved() {
MapSession createSession = this.repository.createSession();
this.repository.save(createSession);
String originalId = createSession.getId();
createSession.changeSessionId();
this.repository.save(createSession);
assertThat(this.repository.findById(originalId)).isNull();
assertThat(this.repository.findById(createSession.getId())).isNotNull();
}
}

View File

@@ -134,6 +134,10 @@ public class MapSessionTests {
return Instant.EPOCH;
}
public String changeSessionId() {
throw new UnsupportedOperationException();
}
public String getId() {
return "id";
}

View File

@@ -76,9 +76,9 @@ public class SessionRepositoryFilterTests {
private Map<String, Session> sessions;
private SessionRepository<Session> sessionRepository;
private SessionRepository<MapSession> sessionRepository;
private SessionRepositoryFilter<Session> filter;
private SessionRepositoryFilter<MapSession> filter;
private MockHttpServletRequest request;
@@ -422,7 +422,7 @@ public class SessionRepositoryFilterTests {
public void doFilterSetsCookieIfChanged() throws Exception {
this.sessionRepository = new MapSessionRepository() {
@Override
public Session findById(String id) {
public MapSession findById(String id) {
return createSession();
}
};
@@ -1256,7 +1256,7 @@ public class SessionRepositoryFilterTests {
@SuppressWarnings("unchecked")
public void doFilterRequestSessionNoRequestSessionNoSessionRepositoryInteractions()
throws Exception {
SessionRepository<Session> sessionRepository = spy(new MapSessionRepository());
SessionRepository<MapSession> sessionRepository = spy(new MapSessionRepository());
this.filter = new SessionRepositoryFilter<>(sessionRepository);
@@ -1283,7 +1283,7 @@ public class SessionRepositoryFilterTests {
@Test
public void doFilterLazySessionCreation() throws Exception {
SessionRepository<Session> sessionRepository = spy(new MapSessionRepository());
SessionRepository<MapSession> sessionRepository = spy(new MapSessionRepository());
this.filter = new SessionRepositoryFilter<>(sessionRepository);
@@ -1299,9 +1299,9 @@ public class SessionRepositoryFilterTests {
@Test
public void doFilterLazySessionUpdates() throws Exception {
Session session = this.sessionRepository.createSession();
MapSession session = this.sessionRepository.createSession();
this.sessionRepository.save(session);
SessionRepository<Session> sessionRepository = spy(this.sessionRepository);
SessionRepository<MapSession> sessionRepository = spy(this.sessionRepository);
setSessionCookie(session.getId());
this.filter = new SessionRepositoryFilter<>(sessionRepository);

View File

@@ -455,6 +455,88 @@ public class RedisOperationsSessionRepositoryITests extends AbstractITests {
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void changeSessionIdWhenOnlyChangeId() throws Exception {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(attrName, attrValue);
this.repository.save(toSave);
RedisSession findById = this.repository.findById(toSave.getId());
assertThat(findById.<String>getAttribute(attrName)).isEqualTo(attrValue);
String originalFindById = findById.getId();
String changeSessionId = findById.changeSessionId();
this.repository.save(findById);
assertThat(this.repository.findById(originalFindById)).isNull();
RedisSession findByChangeSessionId = this.repository.findById(changeSessionId);
assertThat(findByChangeSessionId.<String>getAttribute(attrName)).isEqualTo(attrValue);
}
@Test
public void changeSessionIdWhenChangeTwice() throws Exception {
RedisSession toSave = this.repository.createSession();
this.repository.save(toSave);
String originalId = toSave.getId();
String changeId1 = toSave.changeSessionId();
String changeId2 = toSave.changeSessionId();
this.repository.save(toSave);
assertThat(this.repository.findById(originalId)).isNull();
assertThat(this.repository.findById(changeId1)).isNull();
assertThat(this.repository.findById(changeId2)).isNotNull();
}
@Test
public void changeSessionIdWhenSetAttributeOnChangedSession() throws Exception {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
RedisSession toSave = this.repository.createSession();
this.repository.save(toSave);
RedisSession findById = this.repository.findById(toSave.getId());
findById.setAttribute(attrName, attrValue);
String originalFindById = findById.getId();
String changeSessionId = findById.changeSessionId();
this.repository.save(findById);
assertThat(this.repository.findById(originalFindById)).isNull();
RedisSession findByChangeSessionId = this.repository.findById(changeSessionId);
assertThat(findByChangeSessionId.<String>getAttribute(attrName)).isEqualTo(attrValue);
}
@Test
public void changeSessionIdWhenHasNotSaved() throws Exception {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
RedisSession toSave = this.repository.createSession();
String originalId = toSave.getId();
toSave.changeSessionId();
this.repository.save(toSave);
assertThat(this.repository.findById(toSave.getId())).isNotNull();
assertThat(this.repository.findById(originalId)).isNull();
}
private String getSecurityName() {
return this.context.getAuthentication().getName();
}

View File

@@ -675,6 +675,7 @@ public class RedisOperationsSessionRepository implements
private Map<String, Object> delta = new HashMap<>();
private boolean isNew;
private String originalPrincipalName;
private String originalSessionId;
/**
* Creates a new instance ensuring to mark all of the new attributes to be
@@ -699,6 +700,7 @@ public class RedisOperationsSessionRepository implements
Assert.notNull(cached, "MapSession cannot be null");
this.cached = cached;
this.originalPrincipalName = PRINCIPAL_NAME_RESOLVER.resolvePrincipal(this);
this.originalSessionId = cached.getId();
}
public void setNew(boolean isNew) {
@@ -726,6 +728,10 @@ public class RedisOperationsSessionRepository implements
return this.cached.getId();
}
public String changeSessionId() {
return this.cached.changeSessionId();
}
public Instant getLastAccessedTime() {
return this.cached.getLastAccessedTime();
}
@@ -773,10 +779,11 @@ public class RedisOperationsSessionRepository implements
* session.
*/
private void saveDelta() {
String sessionId = getId();
saveChangeSessionId(sessionId);
if (this.delta.isEmpty()) {
return;
}
String sessionId = getId();
getSessionBoundHashOperations(sessionId).putAll(this.delta);
String principalSessionKey = getSessionAttrNameKey(
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
@@ -806,6 +813,15 @@ public class RedisOperationsSessionRepository implements
RedisOperationsSessionRepository.this.expirationPolicy
.onExpirationUpdated(originalExpiration, this);
}
private void saveChangeSessionId(String sessionId) {
if (!isNew() && !sessionId.equals(this.originalSessionId)) {
String originalSessionIdKey = getSessionKey(this.originalSessionId);
String sessionIdKey = getSessionKey(sessionId);
RedisOperationsSessionRepository.this.sessionRedisOperations.rename(originalSessionIdKey, sessionIdKey);
this.originalSessionId = sessionId;
}
}
}
/**

View File

@@ -131,6 +131,16 @@ public class RedisOperationsSessionRepositoryTests {
this.redisRepository.save(session);
}
@Test
public void changeSessionId() {
RedisSession createSession = this.redisRepository.createSession();
String originalId = createSession.getId();
String changeSessionId = createSession.changeSessionId();
assertThat(originalId).isNotEqualTo(changeSessionId);
assertThat(createSession.getId()).isEqualTo(createSession.getId());
}
@Test
public void createSessionDefaultMaxInactiveInterval() throws Exception {
Session session = this.redisRepository.createSession();

View File

@@ -60,4 +60,93 @@ public abstract class AbstractHazelcastRepositoryITests {
assertThat(hazelcastMap.size()).isEqualTo(0);
}
@Test
public void changeSessionIdWhenOnlyChangeId() throws Exception {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
HazelcastSession toSave = this.repository.createSession();
toSave.setAttribute(attrName, attrValue);
this.repository.save(toSave);
HazelcastSession findById = this.repository.findById(toSave.getId());
assertThat(findById.<String>getAttribute(attrName)).isEqualTo(attrValue);
String originalFindById = findById.getId();
String changeSessionId = findById.changeSessionId();
this.repository.save(findById);
assertThat(this.repository.findById(originalFindById)).isNull();
HazelcastSession findByChangeSessionId = this.repository.findById(changeSessionId);
assertThat(findByChangeSessionId.<String>getAttribute(attrName)).isEqualTo(attrValue);
this.repository.deleteById(changeSessionId);
}
@Test
public void changeSessionIdWhenChangeTwice() throws Exception {
HazelcastSession toSave = this.repository.createSession();
this.repository.save(toSave);
String originalId = toSave.getId();
String changeId1 = toSave.changeSessionId();
String changeId2 = toSave.changeSessionId();
this.repository.save(toSave);
assertThat(this.repository.findById(originalId)).isNull();
assertThat(this.repository.findById(changeId1)).isNull();
assertThat(this.repository.findById(changeId2)).isNotNull();
this.repository.deleteById(changeId2);
}
@Test
public void changeSessionIdWhenSetAttributeOnChangedSession() throws Exception {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
HazelcastSession toSave = this.repository.createSession();
this.repository.save(toSave);
HazelcastSession findById = this.repository.findById(toSave.getId());
findById.setAttribute(attrName, attrValue);
String originalFindById = findById.getId();
String changeSessionId = findById.changeSessionId();
this.repository.save(findById);
assertThat(this.repository.findById(originalFindById)).isNull();
HazelcastSession findByChangeSessionId = this.repository.findById(changeSessionId);
assertThat(findByChangeSessionId.<String>getAttribute(attrName)).isEqualTo(attrValue);
this.repository.deleteById(changeSessionId);
}
@Test
public void changeSessionIdWhenHasNotSaved() throws Exception {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
HazelcastSession toSave = this.repository.createSession();
String originalId = toSave.getId();
toSave.changeSessionId();
this.repository.save(toSave);
assertThat(this.repository.findById(toSave.getId())).isNotNull();
assertThat(this.repository.findById(originalId)).isNull();
this.repository.deleteById(toSave.getId());
}
}

View File

@@ -202,6 +202,10 @@ public class HazelcastSessionRepository implements
}
public void save(HazelcastSession session) {
if (!session.getId().equals(session.originalId)) {
this.sessions.remove(session.originalId);
session.originalId = session.getId();
}
if (session.isChanged()) {
this.sessions.put(session.getId(), session.getDelegate(),
session.getMaxInactiveInterval().getSeconds(), TimeUnit.SECONDS);
@@ -273,6 +277,7 @@ public class HazelcastSessionRepository implements
private final MapSession delegate;
private boolean changed;
private String originalId;
/**
* Creates a new instance ensuring to mark all of the new attributes to be
@@ -292,6 +297,7 @@ public class HazelcastSessionRepository implements
HazelcastSession(MapSession cached) {
Assert.notNull(cached, "MapSession cannot be null");
this.delegate = cached;
this.originalId = cached.getId();
}
public void setLastAccessedTime(Instant lastAccessedTime) {
@@ -312,6 +318,12 @@ public class HazelcastSessionRepository implements
return this.delegate.getId();
}
public String changeSessionId() {
this.changed = true;
String result = this.delegate.changeSessionId();
return result;
}
public Instant getLastAccessedTime() {
return this.delegate.getLastAccessedTime();
}

View File

@@ -83,6 +83,16 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
AuthorityUtils.createAuthorityList("ROLE_USER")));
}
@Test
public void saveWhenNoAttributesThenCanBeFound() throws Exception {
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository
.createSession();
this.repository.save(toSave);
assertThat(this.repository.findById(toSave.getId())).isNotNull();
}
@Test
public void saves() throws InterruptedException {
String username = "saves-" + System.currentTimeMillis();
@@ -560,6 +570,88 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
assertThat(this.repository.findById(session.getId())).isNull();
}
@Test
public void changeSessionIdWhenOnlyChangeId() throws Exception {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
toSave.setAttribute(attrName, attrValue);
this.repository.save(toSave);
JdbcOperationsSessionRepository.JdbcSession findById = this.repository.findById(toSave.getId());
assertThat(findById.<String>getAttribute(attrName)).isEqualTo(attrValue);
String originalFindById = findById.getId();
String changeSessionId = findById.changeSessionId();
this.repository.save(findById);
assertThat(this.repository.findById(originalFindById)).isNull();
JdbcOperationsSessionRepository.JdbcSession findByChangeSessionId = this.repository.findById(changeSessionId);
assertThat(findByChangeSessionId.<String>getAttribute(attrName)).isEqualTo(attrValue);
}
@Test
public void changeSessionIdWhenChangeTwice() throws Exception {
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
this.repository.save(toSave);
String originalId = toSave.getId();
String changeId1 = toSave.changeSessionId();
String changeId2 = toSave.changeSessionId();
this.repository.save(toSave);
assertThat(this.repository.findById(originalId)).isNull();
assertThat(this.repository.findById(changeId1)).isNull();
assertThat(this.repository.findById(changeId2)).isNotNull();
}
@Test
public void changeSessionIdWhenSetAttributeOnChangedSession() throws Exception {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
this.repository.save(toSave);
JdbcOperationsSessionRepository.JdbcSession findById = this.repository.findById(toSave.getId());
findById.setAttribute(attrName, attrValue);
String originalFindById = findById.getId();
String changeSessionId = findById.changeSessionId();
this.repository.save(findById);
assertThat(this.repository.findById(originalFindById)).isNull();
JdbcOperationsSessionRepository.JdbcSession findByChangeSessionId = this.repository.findById(changeSessionId);
assertThat(findByChangeSessionId.<String>getAttribute(attrName)).isEqualTo(attrValue);
}
@Test
public void changeSessionIdWhenHasNotSaved() throws Exception {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
JdbcOperationsSessionRepository.JdbcSession toSave = this.repository.createSession();
String originalId = toSave.getId();
toSave.changeSessionId();
this.repository.save(toSave);
assertThat(this.repository.findById(toSave.getId())).isNotNull();
assertThat(this.repository.findById(originalId)).isNull();
}
private String getSecurityName() {
return this.context.getAuthentication().getName();
}

View File

@@ -27,6 +27,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.sql.DataSource;
@@ -95,25 +96,26 @@ import org.springframework.util.StringUtils;
*
* <pre class="code">
* CREATE TABLE SPRING_SESSION (
* PRIMARY_ID CHAR(36) NOT NULL,
* SESSION_ID CHAR(36),
* CREATION_TIME BIGINT NOT NULL,
* LAST_ACCESS_TIME BIGINT NOT NULL,
* MAX_INACTIVE_INTERVAL INT NOT NULL,
* PRINCIPAL_NAME VARCHAR(100),
* CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (SESSION_ID)
* CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
* );
*
* CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
*
* CREATE TABLE SPRING_SESSION_ATTRIBUTES (
* SESSION_ID CHAR(36),
* SESSION_PRIMARY_ID CHAR(36) NOT NULL,
* ATTRIBUTE_NAME VARCHAR(200),
* ATTRIBUTE_BYTES BYTEA,
* CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
* CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
* CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
* CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
* );
*
* CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_ID);
* CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);
* </pre>
*
* Due to the differences between the various database vendors, especially when it comes
@@ -136,31 +138,31 @@ public class JdbcOperationsSessionRepository implements
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
private static final String CREATE_SESSION_QUERY =
"INSERT INTO %TABLE_NAME%(SESSION_ID, CREATION_TIME, LAST_ACCESS_TIME, MAX_INACTIVE_INTERVAL, PRINCIPAL_NAME) " +
"VALUES (?, ?, ?, ?, ?)";
"INSERT INTO %TABLE_NAME%(PRIMARY_ID, SESSION_ID, CREATION_TIME, LAST_ACCESS_TIME, MAX_INACTIVE_INTERVAL, PRINCIPAL_NAME) " +
"VALUES (?, ?, ?, ?, ?, ?)";
private static final String CREATE_SESSION_ATTRIBUTE_QUERY =
"INSERT INTO %TABLE_NAME%_ATTRIBUTES(SESSION_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) " +
"INSERT INTO %TABLE_NAME%_ATTRIBUTES(SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) " +
"VALUES (?, ?, ?)";
private static final String GET_SESSION_QUERY =
"SELECT S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES " +
"SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES " +
"FROM %TABLE_NAME% S " +
"LEFT OUTER JOIN %TABLE_NAME%_ATTRIBUTES SA ON S.SESSION_ID = SA.SESSION_ID " +
"LEFT OUTER JOIN %TABLE_NAME%_ATTRIBUTES SA ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID " +
"WHERE S.SESSION_ID = ?";
private static final String UPDATE_SESSION_QUERY =
"UPDATE %TABLE_NAME% SET LAST_ACCESS_TIME = ?, MAX_INACTIVE_INTERVAL = ?, PRINCIPAL_NAME = ? " +
"WHERE SESSION_ID = ?";
"UPDATE %TABLE_NAME% SET SESSION_ID = ?, LAST_ACCESS_TIME = ?, MAX_INACTIVE_INTERVAL = ?, PRINCIPAL_NAME = ? " +
"WHERE PRIMARY_ID = ?";
private static final String UPDATE_SESSION_ATTRIBUTE_QUERY =
"UPDATE %TABLE_NAME%_ATTRIBUTES SET ATTRIBUTE_BYTES = ? " +
"WHERE SESSION_ID = ? " +
"WHERE SESSION_PRIMARY_ID = ? " +
"AND ATTRIBUTE_NAME = ?";
private static final String DELETE_SESSION_ATTRIBUTE_QUERY =
"DELETE FROM %TABLE_NAME%_ATTRIBUTES " +
"WHERE SESSION_ID = ? " +
"WHERE SESSION_PRIMARY_ID = ? " +
"AND ATTRIBUTE_NAME = ?";
private static final String DELETE_SESSION_QUERY =
@@ -168,9 +170,9 @@ public class JdbcOperationsSessionRepository implements
"WHERE SESSION_ID = ?";
private static final String LIST_SESSIONS_BY_PRINCIPAL_NAME_QUERY =
"SELECT S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES " +
"SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES " +
"FROM %TABLE_NAME% S " +
"LEFT OUTER JOIN %TABLE_NAME%_ATTRIBUTES SA ON S.SESSION_ID = SA.SESSION_ID " +
"LEFT OUTER JOIN %TABLE_NAME%_ATTRIBUTES SA ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID " +
"WHERE S.PRINCIPAL_NAME = ?";
private static final String DELETE_SESSIONS_BY_LAST_ACCESS_TIME_QUERY =
@@ -186,7 +188,7 @@ public class JdbcOperationsSessionRepository implements
private final TransactionOperations transactionOperations;
private final ResultSetExtractor<List<Session>> extractor = new SessionResultSetExtractor();
private final ResultSetExtractor<List<JdbcSession>> extractor = new SessionResultSetExtractor();
/**
* The name of database table used by Spring Session to store sessions.
@@ -378,11 +380,12 @@ public class JdbcOperationsSessionRepository implements
JdbcOperationsSessionRepository.this.jdbcOperations.update(
JdbcOperationsSessionRepository.this.createSessionQuery,
ps -> {
ps.setString(1, session.getId());
ps.setLong(2, session.getCreationTime().toEpochMilli());
ps.setLong(3, session.getLastAccessedTime().toEpochMilli());
ps.setInt(4, (int) session.getMaxInactiveInterval().getSeconds());
ps.setString(5, session.getPrincipalName());
ps.setString(1, session.primaryKey);
ps.setString(2, session.getId());
ps.setLong(3, session.getCreationTime().toEpochMilli());
ps.setLong(4, session.getLastAccessedTime().toEpochMilli());
ps.setInt(5, (int) session.getMaxInactiveInterval().getSeconds());
ps.setString(6, session.getPrincipalName());
});
if (!session.getAttributeNames().isEmpty()) {
final List<String> attributeNames = new ArrayList<>(session.getAttributeNames());
@@ -392,7 +395,7 @@ public class JdbcOperationsSessionRepository implements
public void setValues(PreparedStatement ps, int i) throws SQLException {
String attributeName = attributeNames.get(i);
ps.setString(1, session.getId());
ps.setString(1, session.primaryKey);
ps.setString(2, attributeName);
serialize(ps, 3, session.getAttribute(attributeName));
}
@@ -415,10 +418,11 @@ public class JdbcOperationsSessionRepository implements
JdbcOperationsSessionRepository.this.jdbcOperations.update(
JdbcOperationsSessionRepository.this.updateSessionQuery,
ps -> {
ps.setLong(1, session.getLastAccessedTime().toEpochMilli());
ps.setInt(2, (int) session.getMaxInactiveInterval().getSeconds());
ps.setString(3, session.getPrincipalName());
ps.setString(4, session.getId());
ps.setString(1, session.getId());
ps.setLong(2, session.getLastAccessedTime().toEpochMilli());
ps.setInt(3, (int) session.getMaxInactiveInterval().getSeconds());
ps.setString(4, session.getPrincipalName());
ps.setString(5, session.primaryKey);
});
}
Map<String, Object> delta = session.getDelta();
@@ -428,7 +432,7 @@ public class JdbcOperationsSessionRepository implements
JdbcOperationsSessionRepository.this.jdbcOperations.update(
JdbcOperationsSessionRepository.this.deleteSessionAttributeQuery,
ps -> {
ps.setString(1, session.getId());
ps.setString(1, session.primaryKey);
ps.setString(2, entry.getKey());
});
}
@@ -437,14 +441,14 @@ public class JdbcOperationsSessionRepository implements
JdbcOperationsSessionRepository.this.updateSessionAttributeQuery,
ps -> {
serialize(ps, 1, entry.getValue());
ps.setString(2, session.getId());
ps.setString(2, session.primaryKey);
ps.setString(3, entry.getKey());
});
if (updatedCount == 0) {
JdbcOperationsSessionRepository.this.jdbcOperations.update(
JdbcOperationsSessionRepository.this.createSessionAttributeQuery,
ps -> {
ps.setString(1, session.getId());
ps.setString(1, session.primaryKey);
ps.setString(2, entry.getKey());
serialize(ps, 3, entry.getValue());
});
@@ -460,8 +464,8 @@ public class JdbcOperationsSessionRepository implements
}
public JdbcSession findById(final String id) {
final Session session = this.transactionOperations.execute(status -> {
List<Session> sessions = JdbcOperationsSessionRepository.this.jdbcOperations.query(
final JdbcSession session = this.transactionOperations.execute(status -> {
List<JdbcSession> sessions = JdbcOperationsSessionRepository.this.jdbcOperations.query(
JdbcOperationsSessionRepository.this.getSessionQuery,
ps -> ps.setString(1, id),
JdbcOperationsSessionRepository.this.extractor
@@ -477,7 +481,7 @@ public class JdbcOperationsSessionRepository implements
deleteById(id);
}
else {
return new JdbcSession(session);
return session;
}
}
return null;
@@ -500,7 +504,7 @@ public class JdbcOperationsSessionRepository implements
return Collections.emptyMap();
}
List<Session> sessions = this.transactionOperations.execute(status ->
List<JdbcSession> sessions = this.transactionOperations.execute(status ->
JdbcOperationsSessionRepository.this.jdbcOperations.query(
JdbcOperationsSessionRepository.this.listSessionsByPrincipalNameQuery,
ps -> ps.setString(1, indexValue),
@@ -509,8 +513,8 @@ public class JdbcOperationsSessionRepository implements
Map<String, JdbcSession> sessionMap = new HashMap<>(
sessions.size());
for (Session session : sessions) {
sessionMap.put(session.getId(), new JdbcSession(session));
for (JdbcSession session : sessions) {
sessionMap.put(session.getId(), session);
}
return sessionMap;
@@ -596,6 +600,8 @@ public class JdbcOperationsSessionRepository implements
private final Session delegate;
private final String primaryKey;
private boolean isNew;
private boolean changed;
@@ -605,10 +611,13 @@ public class JdbcOperationsSessionRepository implements
JdbcSession() {
this.delegate = new MapSession();
this.isNew = true;
this.primaryKey = UUID.randomUUID().toString();
}
JdbcSession(Session delegate) {
JdbcSession(String primaryKey, Session delegate) {
Assert.notNull(primaryKey, "primaryKey cannot be null");
Assert.notNull(delegate, "Session cannot be null");
this.primaryKey = primaryKey;
this.delegate = delegate;
}
@@ -638,6 +647,11 @@ public class JdbcOperationsSessionRepository implements
return this.delegate.getId();
}
public String changeSessionId() {
this.changed = true;
return this.delegate.changeSessionId();
}
public <T> T getAttribute(String attributeName) {
return this.delegate.getAttribute(attributeName);
}
@@ -713,21 +727,23 @@ public class JdbcOperationsSessionRepository implements
}
private class SessionResultSetExtractor implements ResultSetExtractor<List<Session>> {
private class SessionResultSetExtractor implements ResultSetExtractor<List<JdbcSession>> {
public List<Session> extractData(ResultSet rs) throws SQLException, DataAccessException {
List<Session> sessions = new ArrayList<>();
public List<JdbcSession> extractData(ResultSet rs) throws SQLException, DataAccessException {
List<JdbcSession> sessions = new ArrayList<>();
while (rs.next()) {
String id = rs.getString("SESSION_ID");
MapSession session;
JdbcSession session;
if (sessions.size() > 0 && getLast(sessions).getId().equals(id)) {
session = (MapSession) getLast(sessions);
session = getLast(sessions);
}
else {
session = new MapSession(id);
session.setCreationTime(Instant.ofEpochMilli(rs.getLong("CREATION_TIME")));
session.setLastAccessedTime(Instant.ofEpochMilli(rs.getLong("LAST_ACCESS_TIME")));
session.setMaxInactiveInterval(Duration.ofSeconds(rs.getInt("MAX_INACTIVE_INTERVAL")));
MapSession delegate = new MapSession(id);
String primaryKey = rs.getString("PRIMARY_ID");
delegate.setCreationTime(Instant.ofEpochMilli(rs.getLong("CREATION_TIME")));
delegate.setLastAccessedTime(Instant.ofEpochMilli(rs.getLong("LAST_ACCESS_TIME")));
delegate.setMaxInactiveInterval(Duration.ofSeconds(rs.getInt("MAX_INACTIVE_INTERVAL")));
session = new JdbcSession(primaryKey, delegate);
}
String attributeName = rs.getString("ATTRIBUTE_NAME");
if (attributeName != null) {
@@ -738,7 +754,7 @@ public class JdbcOperationsSessionRepository implements
return sessions;
}
private Session getLast(List<Session> sessions) {
private JdbcSession getLast(List<JdbcSession> sessions) {
return sessions.get(sessions.size() - 1);
}

View File

@@ -1,20 +1,22 @@
CREATE TABLE SPRING_SESSION (
PRIMARY_ID CHAR(36) NOT NULL,
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME BIGINT NOT NULL,
LAST_ACCESS_TIME BIGINT NOT NULL,
MAX_INACTIVE_INTERVAL INT NOT NULL,
PRINCIPAL_NAME VARCHAR(100),
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (SESSION_ID)
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
SESSION_ID CHAR(36) NOT NULL,
SESSION_PRIMARY_ID CHAR(36) NOT NULL,
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
ATTRIBUTE_BYTES BLOB NOT NULL,
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_ID);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);

View File

@@ -1,20 +1,22 @@
CREATE TABLE SPRING_SESSION (
PRIMARY_ID CHAR(36) NOT NULL,
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME BIGINT NOT NULL,
LAST_ACCESS_TIME BIGINT NOT NULL,
MAX_INACTIVE_INTERVAL INT NOT NULL,
PRINCIPAL_NAME VARCHAR(100),
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (SESSION_ID)
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
SESSION_ID CHAR(36) NOT NULL,
SESSION_PRIMARY_ID CHAR(36) NOT NULL,
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
ATTRIBUTE_BYTES BLOB NOT NULL,
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_ID);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);

View File

@@ -1,20 +1,22 @@
CREATE TABLE SPRING_SESSION (
PRIMARY_ID CHAR(36) NOT NULL,
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME BIGINT NOT NULL,
LAST_ACCESS_TIME BIGINT NOT NULL,
MAX_INACTIVE_INTERVAL INT NOT NULL,
PRINCIPAL_NAME VARCHAR(100),
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (SESSION_ID)
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
SESSION_ID CHAR(36) NOT NULL,
SESSION_PRIMARY_ID CHAR(36) NOT NULL,
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
ATTRIBUTE_BYTES LONGVARBINARY NOT NULL,
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_ID);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);

View File

@@ -1,20 +1,22 @@
CREATE TABLE SPRING_SESSION (
PRIMARY_ID CHAR(36) NOT NULL,
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME BIGINT NOT NULL,
LAST_ACCESS_TIME BIGINT NOT NULL,
MAX_INACTIVE_INTERVAL INT NOT NULL,
PRINCIPAL_NAME VARCHAR(100),
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (SESSION_ID)
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
SESSION_ID CHAR(36) NOT NULL,
SESSION_PRIMARY_ID CHAR(36) NOT NULL,
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
ATTRIBUTE_BYTES LONGVARBINARY NOT NULL,
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_ID);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);

View File

@@ -1,20 +1,22 @@
CREATE TABLE SPRING_SESSION (
PRIMARY_ID CHAR(36) NOT NULL,
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME BIGINT NOT NULL,
LAST_ACCESS_TIME BIGINT NOT NULL,
MAX_INACTIVE_INTERVAL INT NOT NULL,
PRINCIPAL_NAME VARCHAR(100),
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (SESSION_ID)
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
) ENGINE=InnoDB;
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
SESSION_ID CHAR(36) NOT NULL,
SESSION_PRIMARY_ID CHAR(36) NOT NULL,
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
ATTRIBUTE_BYTES BLOB NOT NULL,
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_ID);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);

View File

@@ -1,20 +1,22 @@
CREATE TABLE SPRING_SESSION (
PRIMARY_ID CHAR(36) NOT NULL,
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME NUMBER(19,0) NOT NULL,
LAST_ACCESS_TIME NUMBER(19,0) NOT NULL,
MAX_INACTIVE_INTERVAL NUMBER(10,0) NOT NULL,
PRINCIPAL_NAME VARCHAR2(100 CHAR),
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (SESSION_ID)
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
SESSION_ID CHAR(36) NOT NULL,
SESSION_PRIMARY_ID CHAR(36) NOT NULL,
ATTRIBUTE_NAME VARCHAR2(200 CHAR) NOT NULL,
ATTRIBUTE_BYTES BLOB NOT NULL,
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_ID);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);

View File

@@ -1,20 +1,22 @@
CREATE TABLE SPRING_SESSION (
PRIMARY_ID CHAR(36) NOT NULL,
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME BIGINT NOT NULL,
LAST_ACCESS_TIME BIGINT NOT NULL,
MAX_INACTIVE_INTERVAL INT NOT NULL,
PRINCIPAL_NAME VARCHAR(100),
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (SESSION_ID)
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
SESSION_ID CHAR(36) NOT NULL,
SESSION_PRIMARY_ID CHAR(36) NOT NULL,
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
ATTRIBUTE_BYTES BYTEA NOT NULL,
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_ID);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);

View File

@@ -1,20 +1,22 @@
CREATE TABLE SPRING_SESSION (
PRIMARY_ID CHARACTER(36) NOT NULL,
SESSION_ID CHARACTER(36) NOT NULL,
CREATION_TIME INTEGER NOT NULL,
LAST_ACCESS_TIME INTEGER NOT NULL,
MAX_INACTIVE_INTERVAL INTEGER NOT NULL,
PRINCIPAL_NAME VARCHAR(100),
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (SESSION_ID)
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
SESSION_ID CHAR(36) NOT NULL,
SESSION_PRIMARY_ID CHAR(36) NOT NULL,
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
ATTRIBUTE_BYTES BLOB NOT NULL,
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_ID);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);

View File

@@ -1,20 +1,22 @@
CREATE TABLE SPRING_SESSION (
PRIMARY_ID CHAR(36) NOT NULL,
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME BIGINT NOT NULL,
LAST_ACCESS_TIME BIGINT NOT NULL,
MAX_INACTIVE_INTERVAL INT NOT NULL,
PRINCIPAL_NAME VARCHAR(100),
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (SESSION_ID)
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
SESSION_ID CHAR(36) NOT NULL,
SESSION_PRIMARY_ID CHAR(36) NOT NULL,
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
ATTRIBUTE_BYTES IMAGE NOT NULL,
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_ID);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);

View File

@@ -1,20 +1,22 @@
CREATE TABLE SPRING_SESSION (
PRIMARY_ID CHAR(36) NOT NULL,
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME BIGINT NOT NULL,
LAST_ACCESS_TIME BIGINT NOT NULL,
MAX_INACTIVE_INTERVAL INT NOT NULL,
PRINCIPAL_NAME VARCHAR(100),
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (SESSION_ID)
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
) LOCK DATAROWS;
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
SESSION_ID CHAR(36) NOT NULL,
SESSION_PRIMARY_ID CHAR(36) NOT NULL,
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
ATTRIBUTE_BYTES IMAGE NOT NULL,
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
) LOCK DATAROWS;
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_ID);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);

View File

@@ -42,6 +42,7 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.MapSession;
import org.springframework.session.Session;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
@@ -357,7 +358,7 @@ public class JdbcOperationsSessionRepositoryTests {
@Test
public void saveUpdatedAttributes() {
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession("primaryKey",
new MapSession());
session.setAttribute("testName", "testValue");
@@ -372,7 +373,7 @@ public class JdbcOperationsSessionRepositoryTests {
@Test
public void saveUpdatedLastAccessedTime() {
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession("primaryKey",
new MapSession());
session.setLastAccessedTime(Instant.now());
@@ -387,7 +388,7 @@ public class JdbcOperationsSessionRepositoryTests {
@Test
public void saveUnchanged() {
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession(
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession("primaryKey",
new MapSession());
this.repository.save(session);
@@ -416,7 +417,7 @@ public class JdbcOperationsSessionRepositoryTests {
@Test
@SuppressWarnings("unchecked")
public void getSessionExpired() {
MapSession expired = new MapSession();
Session expired = this.repository.new JdbcSession();
expired.setLastAccessedTime(Instant.now().minusSeconds(
MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS + 1));
given(this.jdbcOperations.query(isA(String.class),
@@ -437,7 +438,7 @@ public class JdbcOperationsSessionRepositoryTests {
@Test
@SuppressWarnings("unchecked")
public void getSessionFound() {
MapSession saved = new MapSession();
Session saved = this.repository.new JdbcSession("primaryKey", new MapSession());
saved.setAttribute("savedName", "savedValue");
given(this.jdbcOperations.query(isA(String.class),
isA(PreparedStatementSetter.class), isA(ResultSetExtractor.class)))
@@ -500,11 +501,11 @@ public class JdbcOperationsSessionRepositoryTests {
String principal = "username";
Authentication authentication = new UsernamePasswordAuthenticationToken(principal,
"notused", AuthorityUtils.createAuthorityList("ROLE_USER"));
List<MapSession> saved = new ArrayList<>(2);
MapSession saved1 = new MapSession();
List<Session> saved = new ArrayList<>(2);
Session saved1 = this.repository.new JdbcSession();
saved1.setAttribute(SPRING_SECURITY_CONTEXT, authentication);
saved.add(saved1);
MapSession saved2 = new MapSession();
Session saved2 = this.repository.new JdbcSession();
saved2.setAttribute(SPRING_SECURITY_CONTEXT, authentication);
saved.add(saved2);
given(this.jdbcOperations.query(isA(String.class),