Automatically Index SecurityContext

Fixes gh-266
This commit is contained in:
Rob Winch
2016-01-29 16:27:19 -06:00
parent ad09b498a3
commit f20acbf9b9
8 changed files with 336 additions and 179 deletions

View File

@@ -24,12 +24,17 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.Bean;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
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.FindByIndexNameSessionRepository;
import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession;
@@ -67,14 +72,25 @@ import com.gemstone.gemfire.pdx.PdxWriter;
@ContextConfiguration
@WebAppConfiguration
public class GemFireOperationsSessionRepositoryIntegrationTests extends AbstractGemFireIntegrationTests {
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 300;
private static final String GEMFIRE_LOG_LEVEL = "warning";
private static final String SPRING_SESSION_GEMFIRE_REGION_NAME = "TestPartitionedSessions";
SecurityContext context;
SecurityContext changedContext;
@Before
public void setup() {
context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(new UsernamePasswordAuthenticationToken("username-"+UUID.randomUUID(), "na", AuthorityUtils.createAuthorityList("ROLE_USER")));
changedContext = SecurityContextHolder.createEmptyContext();
changedContext.setAuthentication(new UsernamePasswordAuthenticationToken("changedContext-"+UUID.randomUUID(), "na", AuthorityUtils.createAuthorityList("ROLE_USER")));
assertThat(gemfireCache).isNotNull();
assertThat(gemfireSessionRepository).isNotNull();
assertThat(gemfireSessionRepository.getMaxInactiveIntervalInSeconds()).isEqualTo(
@@ -159,6 +175,34 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
assertThat(robWinchSessions.get(sessionFive.getId())).isEqualTo(sessionFive);
}
@Test
public void findSessionsBySecurityPrincipalName() {
ExpiringSession toSave = this.gemfireSessionRepository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
save(toSave);
Map<String, ExpiringSession> findByPrincipalName = doFindByPrincipalName(getSecurityName());
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findSessionsByChangedSecurityPrincipalName() {
ExpiringSession toSave = this.gemfireSessionRepository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
save(toSave);
toSave.setAttribute(SPRING_SECURITY_CONTEXT, changedContext);
save(toSave);
Map<String, ExpiringSession> findByPrincipalName = doFindByPrincipalName(getSecurityName());
assertThat(findByPrincipalName).isEmpty();
findByPrincipalName = doFindByPrincipalName(getChangedSecurityName());
assertThat(findByPrincipalName).hasSize(1);
}
@Test
public void findsNoSessionsByNonExistingPrincipal() {
Map<String, ExpiringSession> nonExistingPrincipalSessions = doFindByPrincipalName("nonExistingPrincipalName");
@@ -217,6 +261,14 @@ public class GemFireOperationsSessionRepositoryIntegrationTests extends Abstract
assertThat(savedSession.getAttribute(expectedAttributeNames.get(3))).isEqualTo(jonDoe);
}
private String getSecurityName() {
return context.getAuthentication().getName();
}
private String getChangedSecurityName() {
return changedContext.getAuthentication().getName();
}
@EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME,
maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
static class SpringSessionGemFireConfiguration {

View File

@@ -49,6 +49,10 @@ import org.springframework.test.context.web.WebAppConfiguration;
@ContextConfiguration
@WebAppConfiguration
public class RedisOperationsSessionRepositoryITests {
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
private static final String INDEX_NAME = FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME;
@Autowired
private RedisOperationsSessionRepository repository;
@@ -58,26 +62,37 @@ public class RedisOperationsSessionRepositoryITests {
@Autowired
RedisOperations<Object, Object> redis;
SecurityContext context;
SecurityContext changedContext;
@Before
public void setup() {
registry.clear();
context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(new UsernamePasswordAuthenticationToken("username-"+UUID.randomUUID(), "na", AuthorityUtils.createAuthorityList("ROLE_USER")));
changedContext = SecurityContextHolder.createEmptyContext();
changedContext.setAuthentication(new UsernamePasswordAuthenticationToken("changedContext-"+UUID.randomUUID(), "na", AuthorityUtils.createAuthorityList("ROLE_USER")));
}
@Test
public void saves() throws InterruptedException {
String username = "saves-"+System.currentTimeMillis();
String username = "saves-" + System.currentTimeMillis();
String usernameSessionKey = "spring:session:RedisOperationsSessionRepositoryITests:index:" + FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME + ":" + username;
String usernameSessionKey = "spring:session:RedisOperationsSessionRepositoryITests:index:" + INDEX_NAME + ":"
+ username;
RedisSession toSave = repository.createSession();
String expectedAttributeName = "a";
String expectedAttributeValue = "b";
toSave.setAttribute(expectedAttributeName, expectedAttributeValue);
Authentication toSaveToken = new UsernamePasswordAuthenticationToken(username,"password", AuthorityUtils.createAuthorityList("ROLE_USER"));
Authentication toSaveToken = new UsernamePasswordAuthenticationToken(username, "password",
AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContext toSaveContext = SecurityContextHolder.createEmptyContext();
toSaveContext.setAuthentication(toSaveToken);
toSave.setAttribute("SPRING_SECURITY_CONTEXT", toSaveContext);
toSave.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username);
toSave.setAttribute(SPRING_SECURITY_CONTEXT, toSaveContext);
toSave.setAttribute(INDEX_NAME, username);
registry.clear();
repository.save(toSave);
@@ -100,8 +115,8 @@ public class RedisOperationsSessionRepositoryITests {
assertThat(registry.getEvent()).isInstanceOf(SessionDestroyedEvent.class);
assertThat(redis.boundSetOps(usernameSessionKey).members()).doesNotContain(toSave.getId());
assertThat(registry.getEvent().getSession().getAttribute(expectedAttributeName)).isEqualTo(expectedAttributeValue);
assertThat(registry.getEvent().getSession().getAttribute(expectedAttributeName))
.isEqualTo(expectedAttributeValue);
}
@Test
@@ -125,15 +140,18 @@ public class RedisOperationsSessionRepositoryITests {
repository.delete(toSave.getId());
}
@Test
public void findByPrincipalName() throws Exception {
String principalName = "findByPrincipalName" + UUID.randomUUID();
RedisSession toSave = repository.createSession();
toSave.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName);
toSave.setAttribute(INDEX_NAME, principalName);
repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
@@ -141,7 +159,7 @@ public class RedisOperationsSessionRepositoryITests {
repository.delete(toSave.getId());
registry.receivedEvent();
findByPrincipalName = repository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName);
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
assertThat(findByPrincipalName).hasSize(0);
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
@@ -151,7 +169,7 @@ public class RedisOperationsSessionRepositoryITests {
public void findByPrincipalNameExpireRemovesIndex() throws Exception {
String principalName = "findByPrincipalNameExpireRemovesIndex" + UUID.randomUUID();
RedisSession toSave = repository.createSession();
toSave.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName);
toSave.setAttribute(INDEX_NAME, principalName);
repository.save(toSave);
@@ -159,9 +177,10 @@ public class RedisOperationsSessionRepositoryITests {
String channel = ":expired";
DefaultMessage message = new DefaultMessage(channel.getBytes("UTF-8"), body.getBytes("UTF-8"));
byte[] pattern = new byte[] {};
repository.onMessage(message , pattern);
repository.onMessage(message, pattern);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,principalName);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).hasSize(0);
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
@@ -171,14 +190,15 @@ public class RedisOperationsSessionRepositoryITests {
public void findByPrincipalNameNoPrincipalNameChange() throws Exception {
String principalName = "findByPrincipalNameNoPrincipalNameChange" + UUID.randomUUID();
RedisSession toSave = repository.createSession();
toSave.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName);
toSave.setAttribute(INDEX_NAME, principalName);
repository.save(toSave);
toSave.setAttribute("other", "value");
repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,principalName);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
@@ -188,7 +208,7 @@ public class RedisOperationsSessionRepositoryITests {
public void findByPrincipalNameNoPrincipalNameChangeReload() throws Exception {
String principalName = "findByPrincipalNameNoPrincipalNameChangeReload" + UUID.randomUUID();
RedisSession toSave = repository.createSession();
toSave.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName);
toSave.setAttribute(INDEX_NAME, principalName);
repository.save(toSave);
@@ -197,7 +217,8 @@ public class RedisOperationsSessionRepositoryITests {
toSave.setAttribute("other", "value");
repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,principalName);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
@@ -207,14 +228,15 @@ public class RedisOperationsSessionRepositoryITests {
public void findByDeletedPrincipalName() throws Exception {
String principalName = "findByDeletedPrincipalName" + UUID.randomUUID();
RedisSession toSave = repository.createSession();
toSave.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName);
toSave.setAttribute(INDEX_NAME, principalName);
repository.save(toSave);
toSave.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, null);
toSave.setAttribute(INDEX_NAME, null);
repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,principalName);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).isEmpty();
}
@@ -224,17 +246,18 @@ public class RedisOperationsSessionRepositoryITests {
String principalName = "findByChangedPrincipalName" + UUID.randomUUID();
String principalNameChanged = "findByChangedPrincipalName" + UUID.randomUUID();
RedisSession toSave = repository.createSession();
toSave.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName);
toSave.setAttribute(INDEX_NAME, principalName);
repository.save(toSave);
toSave.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalNameChanged);
toSave.setAttribute(INDEX_NAME, principalNameChanged);
repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,principalName);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).isEmpty();
findByPrincipalName = repository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,principalNameChanged);
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, principalNameChanged);
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
@@ -244,15 +267,16 @@ public class RedisOperationsSessionRepositoryITests {
public void findByDeletedPrincipalNameReload() throws Exception {
String principalName = "findByDeletedPrincipalName" + UUID.randomUUID();
RedisSession toSave = repository.createSession();
toSave.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName);
toSave.setAttribute(INDEX_NAME, principalName);
repository.save(toSave);
RedisSession getSession = repository.getSession(toSave.getId());
getSession.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, null);
getSession.setAttribute(INDEX_NAME, null);
repository.save(getSession);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,principalName);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).isEmpty();
}
@@ -262,24 +286,186 @@ public class RedisOperationsSessionRepositoryITests {
String principalName = "findByChangedPrincipalName" + UUID.randomUUID();
String principalNameChanged = "findByChangedPrincipalName" + UUID.randomUUID();
RedisSession toSave = repository.createSession();
toSave.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName);
toSave.setAttribute(INDEX_NAME, principalName);
repository.save(toSave);
RedisSession getSession = repository.getSession(toSave.getId());
getSession.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalNameChanged);
getSession.setAttribute(INDEX_NAME, principalNameChanged);
repository.save(getSession);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,principalName);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).isEmpty();
findByPrincipalName = repository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,principalNameChanged);
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, principalNameChanged);
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findBySecurityPrincipalName() throws Exception {
RedisSession toSave = repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
repository.delete(toSave.getId());
registry.receivedEvent();
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
assertThat(findByPrincipalName).hasSize(0);
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
}
@Test
public void findBySecurityPrincipalNameExpireRemovesIndex() throws Exception {
RedisSession toSave = repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
repository.save(toSave);
String body = "spring:session:RedisOperationsSessionRepositoryITests:sessions:expires:" + toSave.getId();
String channel = ":expired";
DefaultMessage message = new DefaultMessage(channel.getBytes("UTF-8"), body.getBytes("UTF-8"));
byte[] pattern = new byte[] {};
repository.onMessage(message, pattern);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).hasSize(0);
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
}
@Test
public void findByPrincipalNameNoSecurityPrincipalNameChange() throws Exception {
RedisSession toSave = repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
repository.save(toSave);
toSave.setAttribute("other", "value");
repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findByPrincipalNameNoSecurityPrincipalNameChangeReload() throws Exception {
RedisSession toSave = repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
repository.save(toSave);
toSave = repository.getSession(toSave.getId());
toSave.setAttribute("other", "value");
repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findByDeletedSecurityPrincipalName() throws Exception {
RedisSession toSave = repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
repository.save(toSave);
toSave.setAttribute(SPRING_SECURITY_CONTEXT, null);
repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).isEmpty();
}
@Test
public void findByChangedSecurityPrincipalName() throws Exception {
RedisSession toSave = repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
repository.save(toSave);
toSave.setAttribute(SPRING_SECURITY_CONTEXT, changedContext);
repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).isEmpty();
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findByDeletedSecurityPrincipalNameReload() throws Exception {
RedisSession toSave = repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
repository.save(toSave);
RedisSession getSession = repository.getSession(toSave.getId());
getSession.setAttribute(INDEX_NAME, null);
repository.save(getSession);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
getChangedSecurityName());
assertThat(findByPrincipalName).isEmpty();
}
@Test
public void findByChangedSecurityPrincipalNameReload() throws Exception {
RedisSession toSave = repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, context);
repository.save(toSave);
RedisSession getSession = repository.getSession(toSave.getId());
getSession.setAttribute(SPRING_SECURITY_CONTEXT, changedContext);
repository.save(getSession);
Map<String, RedisSession> findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).isEmpty();
findByPrincipalName = repository.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
private String getSecurityName() {
return context.getAuthentication().getName();
}
private String getChangedSecurityName() {
return changedContext.getAuthentication().getName();
}
@Configuration
@EnableRedisHttpSession(redisNamespace = "RedisOperationsSessionRepositoryITests")
static class Config {