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

@@ -438,6 +438,46 @@ class ReactiveRedisSessionRepositoryTests {
verifyNoMoreInteractions(this.hashOperations);
}
@Test
void createSessionWhenSessionIdGenerationStrategyThenUses() {
this.repository.setSessionIdGenerationStrategy(() -> "test");
this.repository.createSession().as(StepVerifier::create).assertNext((redisSession) -> {
assertThat(redisSession.getId()).isEqualTo("test");
assertThat(redisSession.changeSessionId()).isEqualTo("test");
}).verifyComplete();
}
@Test
void setSessionIdGenerationStrategyWhenNullThenThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.repository.setSessionIdGenerationStrategy(null))
.withMessage("sessionIdGenerationStrategy cannot be null");
}
@Test
@SuppressWarnings("unchecked")
void findByIdWhenChangeSessionIdThenUsesSessionIdGenerationStrategy() {
this.repository.setSessionIdGenerationStrategy(() -> "changed-session-id");
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
String attribute1 = "attribute1";
String attribute2 = "attribute2";
MapSession expected = new MapSession("test");
expected.setLastAccessedTime(Instant.now().minusSeconds(60));
expected.setAttribute(attribute1, "test");
expected.setAttribute(attribute2, null);
Map map = map(RedisSessionMapper.ATTRIBUTE_PREFIX + attribute1, expected.getAttribute(attribute1),
RedisSessionMapper.ATTRIBUTE_PREFIX + attribute2, expected.getAttribute(attribute2),
RedisSessionMapper.CREATION_TIME_KEY, expected.getCreationTime().toEpochMilli(),
RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY, (int) expected.getMaxInactiveInterval().getSeconds(),
RedisSessionMapper.LAST_ACCESSED_TIME_KEY, expected.getLastAccessedTime().toEpochMilli());
given(this.hashOperations.entries(anyString())).willReturn(Flux.fromIterable(map.entrySet()));
StepVerifier.create(this.repository.findById("test")).consumeNextWith((session) -> {
assertThat(session.getId()).isEqualTo(expected.getId());
assertThat(session.changeSessionId()).isEqualTo("changed-session-id");
}).verifyComplete();
}
private Map<String, Object> map(Object... objects) {
Map<String, Object> result = new HashMap<>();
if (objects == null) {

View File

@@ -910,6 +910,46 @@ class RedisIndexedSessionRepositoryTests {
assertThat(getDelta()).hasSize(3);
}
@Test
void createSessionWhenSessionIdGenerationStrategyThenUses() {
this.redisRepository.setSessionIdGenerationStrategy(() -> "test");
RedisSession session = this.redisRepository.createSession();
assertThat(session.getId()).isEqualTo("test");
assertThat(session.changeSessionId()).isEqualTo("test");
}
@Test
void setSessionIdGenerationStrategyWhenNullThenThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.redisRepository.setSessionIdGenerationStrategy(null))
.withMessage("sessionIdGenerationStrategy cannot be null");
}
@Test
void findByIdWhenChangeSessionIdThenUsesSessionIdGenerationStrategy() {
this.redisRepository.setSessionIdGenerationStrategy(() -> "test");
String attribute1 = "attribute1";
String attribute2 = "attribute2";
MapSession expected = new MapSession("original");
expected.setLastAccessedTime(Instant.now().minusSeconds(60));
expected.setAttribute(attribute1, "test");
expected.setAttribute(attribute2, null);
given(this.redisOperations.<String, Object>boundHashOps(getKey(expected.getId())))
.willReturn(this.boundHashOperations);
Map<String, Object> map = map(RedisIndexedSessionRepository.getSessionAttrNameKey(attribute1),
expected.getAttribute(attribute1), RedisIndexedSessionRepository.getSessionAttrNameKey(attribute2),
expected.getAttribute(attribute2), RedisSessionMapper.CREATION_TIME_KEY,
expected.getCreationTime().toEpochMilli(), RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
(int) expected.getMaxInactiveInterval().getSeconds(), RedisSessionMapper.LAST_ACCESSED_TIME_KEY,
expected.getLastAccessedTime().toEpochMilli());
given(this.boundHashOperations.entries()).willReturn(map);
RedisSession session = this.redisRepository.findById(expected.getId());
String oldSessionId = session.getId();
String newSessionId = session.changeSessionId();
assertThat(oldSessionId).isEqualTo("original");
assertThat(newSessionId).isEqualTo("test");
}
private String getKey(String id) {
return "spring:session:sessions:" + id;
}

View File

@@ -373,6 +373,35 @@ class RedisSessionRepositoryTests {
verifyNoMoreInteractions(this.sessionHashOperations);
}
@Test
void createSessionWhenSessionIdGenerationStrategyThenUses() {
this.sessionRepository.setSessionIdGenerationStrategy(() -> "test");
RedisSessionRepository.RedisSession session = this.sessionRepository.createSession();
assertThat(session.getId()).isEqualTo("test");
assertThat(session.changeSessionId()).isEqualTo("test");
}
@Test
void setSessionIdGenerationStrategyWhenNullThenThrowsException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.sessionRepository.setSessionIdGenerationStrategy(null))
.withMessage("sessionIdGenerationStrategy cannot be null");
}
@Test
void findByIdWhenChangeSessionIdThenUsesSessionIdGenerationStrategy() {
this.sessionRepository.setSessionIdGenerationStrategy(() -> "test");
Instant now = Instant.now().truncatedTo(ChronoUnit.MILLIS);
given(this.sessionHashOperations.entries(eq(TEST_SESSION_KEY)))
.willReturn(mapOf(RedisSessionMapper.CREATION_TIME_KEY, Instant.EPOCH.toEpochMilli(),
RedisSessionMapper.LAST_ACCESSED_TIME_KEY, now.toEpochMilli(),
RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY, MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS,
RedisSessionMapper.ATTRIBUTE_PREFIX + "attribute1", "value1"));
RedisSession session = this.sessionRepository.findById(TEST_SESSION_ID);
assertThat(session.getId()).isEqualTo(TEST_SESSION_ID);
assertThat(session.changeSessionId()).isEqualTo("test");
}
private static String getSessionKey(String sessionId) {
return "spring:session:sessions:" + sessionId;
}

View File

@@ -39,6 +39,8 @@ import org.springframework.data.redis.core.RedisOperations;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.session.FlushMode;
import org.springframework.session.SaveMode;
import org.springframework.session.SessionIdGenerationStrategy;
import org.springframework.session.UuidSessionIdGenerationStrategy;
import org.springframework.session.config.SessionRepositoryCustomizer;
import org.springframework.session.data.redis.RedisSessionRepository;
import org.springframework.session.data.redis.config.annotation.SpringSessionRedisConnectionFactory;
@@ -206,6 +208,22 @@ class RedisHttpsSessionConfigurationTests {
assertThat(sessionRepository).extracting("defaultMaxInactiveInterval").isEqualTo(Duration.ZERO);
}
@Test
void registerWhenSessionIdGenerationStrategyBeanThenUses() {
registerAndRefresh(RedisConfig.class, SessionIdGenerationStrategyConfiguration.class);
RedisSessionRepository sessionRepository = this.context.getBean(RedisSessionRepository.class);
assertThat(sessionRepository).extracting("sessionIdGenerationStrategy")
.isInstanceOf(TestSessionIdGenerationStrategy.class);
}
@Test
void registerWhenNoSessionIdGenerationStrategyBeanThenDefault() {
registerAndRefresh(RedisConfig.class, DefaultConfiguration.class);
RedisSessionRepository sessionRepository = this.context.getBean(RedisSessionRepository.class);
assertThat(sessionRepository).extracting("sessionIdGenerationStrategy")
.isInstanceOf(UuidSessionIdGenerationStrategy.class);
}
private void registerAndRefresh(Class<?>... annotatedClasses) {
this.context.register(annotatedClasses);
this.context.refresh();
@@ -381,4 +399,30 @@ class RedisHttpsSessionConfigurationTests {
}
@Configuration(proxyBeanMethods = false)
@EnableRedisHttpSession
static class SessionIdGenerationStrategyConfiguration {
@Bean
SessionIdGenerationStrategy sessionIdGenerationStrategy() {
return new TestSessionIdGenerationStrategy();
}
}
@Configuration(proxyBeanMethods = false)
@EnableRedisHttpSession
static class DefaultConfiguration {
}
static class TestSessionIdGenerationStrategy implements SessionIdGenerationStrategy {
@Override
public String generate() {
return "test";
}
}
}

View File

@@ -43,6 +43,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.data.redis.RedisIndexedSessionRepository;
import org.springframework.session.data.redis.config.annotation.SpringSessionRedisConnectionFactory;
@@ -240,6 +242,22 @@ class RedisIndexedHttpSessionConfigurationTests {
assertThat(sessionRepository).extracting("defaultMaxInactiveInterval").isEqualTo(Duration.ZERO);
}
@Test
void registerWhenSessionIdGenerationStrategyBeanThenUses() {
registerAndRefresh(RedisConfig.class, SessionIdGenerationStrategyConfiguration.class);
RedisIndexedSessionRepository sessionRepository = this.context.getBean(RedisIndexedSessionRepository.class);
assertThat(sessionRepository).extracting("sessionIdGenerationStrategy")
.isInstanceOf(TestSessionIdGenerationStrategy.class);
}
@Test
void registerWhenNoSessionIdGenerationStrategyBeanThenDefault() {
registerAndRefresh(RedisConfig.class, DefaultConfiguration.class);
RedisIndexedSessionRepository sessionRepository = this.context.getBean(RedisIndexedSessionRepository.class);
assertThat(sessionRepository).extracting("sessionIdGenerationStrategy")
.isInstanceOf(UuidSessionIdGenerationStrategy.class);
}
private void registerAndRefresh(Class<?>... annotatedClasses) {
this.context.register(annotatedClasses);
this.context.refresh();
@@ -444,4 +462,30 @@ class RedisIndexedHttpSessionConfigurationTests {
}
@Configuration(proxyBeanMethods = false)
@EnableRedisIndexedHttpSession
static class SessionIdGenerationStrategyConfiguration {
@Bean
SessionIdGenerationStrategy sessionIdGenerationStrategy() {
return new TestSessionIdGenerationStrategy();
}
}
@Configuration(proxyBeanMethods = false)
@EnableRedisIndexedHttpSession
static class DefaultConfiguration {
}
static class TestSessionIdGenerationStrategy implements SessionIdGenerationStrategy {
@Override
public String generate() {
return "test";
}
}
}