Introduce SessionIdGenerationStrategy

Closes gh-11
This commit is contained in:
Marcus Da Coregio
2023-03-07 17:55:18 -03:00
committed by Marcus Hert Da Coregio
parent 2e1275333a
commit d547b33962
39 changed files with 1074 additions and 30 deletions

View File

@@ -48,6 +48,8 @@ import org.springframework.session.MapSession;
import org.springframework.session.PrincipalNameIndexResolver;
import org.springframework.session.SaveMode;
import org.springframework.session.Session;
import org.springframework.session.SessionIdGenerationStrategy;
import org.springframework.session.UuidSessionIdGenerationStrategy;
import org.springframework.session.events.AbstractSessionEvent;
import org.springframework.session.events.SessionCreatedEvent;
import org.springframework.session.events.SessionDeletedEvent;
@@ -151,6 +153,8 @@ public class HazelcastIndexedSessionRepository
private UUID sessionListenerId;
private SessionIdGenerationStrategy sessionIdGenerationStrategy = UuidSessionIdGenerationStrategy.getInstance();
/**
* Create a new {@link HazelcastIndexedSessionRepository} instance.
* @param hazelcastInstance the {@link HazelcastInstance} to use for managing sessions
@@ -245,7 +249,7 @@ public class HazelcastIndexedSessionRepository
@Override
public HazelcastSession createSession() {
MapSession cached = new MapSession();
MapSession cached = new MapSession(this.sessionIdGenerationStrategy);
cached.setMaxInactiveInterval(this.defaultMaxInactiveInterval);
HazelcastSession session = new HazelcastSession(cached, true);
session.flushImmediateIfNecessary();
@@ -349,6 +353,16 @@ public class HazelcastIndexedSessionRepository
this.eventPublisher.publishEvent(new SessionExpiredEvent(this, event.getOldValue()));
}
/**
* Set the {@link SessionIdGenerationStrategy} to use to generate session ids.
* @param sessionIdGenerationStrategy the {@link SessionIdGenerationStrategy} to use
* @since 3.2
*/
public void setSessionIdGenerationStrategy(SessionIdGenerationStrategy sessionIdGenerationStrategy) {
Assert.notNull(sessionIdGenerationStrategy, "sessionIdGenerationStrategy cannot be null");
this.sessionIdGenerationStrategy = sessionIdGenerationStrategy;
}
/**
* A custom implementation of {@link Session} that uses a {@link MapSession} as the
* basis for its mapping. It keeps track if changes have been made since last save.
@@ -405,7 +419,8 @@ public class HazelcastIndexedSessionRepository
@Override
public String changeSessionId() {
String newSessionId = this.delegate.changeSessionId();
String newSessionId = HazelcastIndexedSessionRepository.this.sessionIdGenerationStrategy.generate();
this.delegate.setId(newSessionId);
this.sessionIdChanged = true;
return newSessionId;
}

View File

@@ -38,6 +38,8 @@ import org.springframework.session.IndexResolver;
import org.springframework.session.MapSession;
import org.springframework.session.SaveMode;
import org.springframework.session.Session;
import org.springframework.session.SessionIdGenerationStrategy;
import org.springframework.session.UuidSessionIdGenerationStrategy;
import org.springframework.session.config.SessionRepositoryCustomizer;
import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration;
import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository;
@@ -75,6 +77,8 @@ public class HazelcastHttpSessionConfiguration implements ImportAware {
private List<SessionRepositoryCustomizer<HazelcastIndexedSessionRepository>> sessionRepositoryCustomizers;
private SessionIdGenerationStrategy sessionIdGenerationStrategy = UuidSessionIdGenerationStrategy.getInstance();
@Bean
public FindByIndexNameSessionRepository<?> sessionRepository() {
return createHazelcastIndexedSessionRepository();
@@ -158,9 +162,15 @@ public class HazelcastHttpSessionConfiguration implements ImportAware {
sessionRepository.setDefaultMaxInactiveInterval(this.maxInactiveInterval);
sessionRepository.setFlushMode(this.flushMode);
sessionRepository.setSaveMode(this.saveMode);
sessionRepository.setSessionIdGenerationStrategy(this.sessionIdGenerationStrategy);
this.sessionRepositoryCustomizers
.forEach((sessionRepositoryCustomizer) -> sessionRepositoryCustomizer.customize(sessionRepository));
return sessionRepository;
}
@Autowired(required = false)
public void setSessionIdGenerationStrategy(SessionIdGenerationStrategy sessionIdGenerationStrategy) {
this.sessionIdGenerationStrategy = sessionIdGenerationStrategy;
}
}

View File

@@ -465,4 +465,31 @@ class HazelcastIndexedSessionRepositoryTests {
verifyNoMoreInteractions(this.sessions);
}
@Test
void createSessionWhenSessionIdGenerationStrategyThenUses() {
this.repository.setSessionIdGenerationStrategy(() -> "test");
HazelcastSession session = this.repository.createSession();
assertThat(session.getId()).isEqualTo("test");
assertThat(session.changeSessionId()).isEqualTo("test");
}
@Test
void setSessionIdGenerationStrategyWhenNullThenThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.repository.setSessionIdGenerationStrategy(null))
.withMessage("sessionIdGenerationStrategy cannot be null");
}
@Test
void findByIdWhenChangeSessionIdThenUsesSessionIdGenerationStrategy() {
this.repository.setSessionIdGenerationStrategy(() -> "test");
MapSession saved = new MapSession("original");
saved.setAttribute("savedName", "savedValue");
given(this.sessions.get(eq(saved.getId()))).willReturn(saved);
HazelcastSession session = this.repository.findById(saved.getId());
assertThat(session.getId()).isEqualTo(saved.getId());
assertThat(session.changeSessionId()).isEqualTo("test");
}
}

View File

@@ -36,6 +36,8 @@ import org.springframework.session.FlushMode;
import org.springframework.session.IndexResolver;
import org.springframework.session.SaveMode;
import org.springframework.session.Session;
import org.springframework.session.SessionIdGenerationStrategy;
import org.springframework.session.UuidSessionIdGenerationStrategy;
import org.springframework.session.config.SessionRepositoryCustomizer;
import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository;
import org.springframework.session.hazelcast.config.annotation.SpringSessionHazelcastInstance;
@@ -238,6 +240,24 @@ class HazelcastHttpSessionConfigurationTests {
assertThat(sessionRepository).extracting("defaultMaxInactiveInterval").isEqualTo(Duration.ZERO);
}
@Test
void registerWhenSessionIdGenerationStrategyBeanThenUses() {
registerAndRefresh(DefaultConfiguration.class, SessionIdGenerationStrategyConfiguration.class);
HazelcastIndexedSessionRepository sessionRepository = this.context
.getBean(HazelcastIndexedSessionRepository.class);
assertThat(sessionRepository).extracting("sessionIdGenerationStrategy")
.isInstanceOf(TestSessionIdGenerationStrategy.class);
}
@Test
void registerWhenNoSessionIdGenerationStrategyBeanThenDefault() {
registerAndRefresh(DefaultConfiguration.class);
HazelcastIndexedSessionRepository sessionRepository = this.context
.getBean(HazelcastIndexedSessionRepository.class);
assertThat(sessionRepository).extracting("sessionIdGenerationStrategy")
.isInstanceOf(UuidSessionIdGenerationStrategy.class);
}
private void registerAndRefresh(Class<?>... annotatedClasses) {
this.context.register(annotatedClasses);
this.context.refresh();
@@ -465,4 +485,23 @@ class HazelcastHttpSessionConfigurationTests {
}
@Configuration(proxyBeanMethods = false)
static class SessionIdGenerationStrategyConfiguration {
@Bean
SessionIdGenerationStrategy sessionIdGenerationStrategy() {
return new TestSessionIdGenerationStrategy();
}
}
static class TestSessionIdGenerationStrategy implements SessionIdGenerationStrategy {
@Override
public String generate() {
return "test";
}
}
}