SEC-1039: Created new filter SecurityContextPersistenceFilter and SecurityContextRepository strategy to replace HttpSessionContextIntegrationFilter functionality.
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
package org.springframework.security.context;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.providers.TestingAuthenticationToken;
|
||||
|
||||
public class HttpSessionSecurityContextRepositoryTests {
|
||||
private final TestingAuthenticationToken testToken = new TestingAuthenticationToken("someone", "passwd", "ROLE_A");
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void detectsInvalidContextClass() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
repo.setSecurityContextClass(String.class);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void cannotSetNullContextClass() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
repo.setSecurityContextClass(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sessionIsntCreatedIfContextDoesntChange() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContext context = repo.loadContext(holder);
|
||||
assertNull(request.getSession(false));
|
||||
repo.saveContext(context, holder.getRequest(), holder.getResponse());
|
||||
assertNull(request.getSession(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sessionIsntCreatedIfAllowSessionCreationIsFalse() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
repo.setAllowSessionCreation(false);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContext context = repo.loadContext(holder);
|
||||
// Change context
|
||||
context.setAuthentication(testToken);
|
||||
repo.saveContext(context, holder.getRequest(), holder.getResponse());
|
||||
assertNull(request.getSession(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void existingContextIsSuccessFullyLoadedFromSessionAndSavedBack() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
SecurityContextHolder.getContext().setAuthentication(testToken);
|
||||
request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContext context = repo.loadContext(holder);
|
||||
assertNotNull(context);
|
||||
assertEquals(testToken, context.getAuthentication());
|
||||
// Won't actually be saved as it hasn't changed, but go through the use case anyway
|
||||
repo.saveContext(context, holder.getRequest(), holder.getResponse());
|
||||
assertEquals(context, request.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonSecurityContextInSessionIsIgnored() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
SecurityContextHolder.getContext().setAuthentication(testToken);
|
||||
request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, "NotASecurityContextInstance");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContext context = repo.loadContext(holder);
|
||||
assertNotNull(context);
|
||||
assertNull(context.getAuthentication());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sessionIsCreatedAndContextStoredWhenContextChanges() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContext context = repo.loadContext(holder);
|
||||
assertNull(request.getSession(false));
|
||||
// Simulate authentication during the request
|
||||
context.setAuthentication(testToken);
|
||||
repo.saveContext(context, holder.getRequest(), holder.getResponse());
|
||||
assertNotNull(request.getSession(false));
|
||||
assertEquals(context, request.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void redirectCausesEarlySaveOfContext() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContextHolder.setContext(repo.loadContext(holder));
|
||||
SecurityContextHolder.getContext().setAuthentication(testToken);
|
||||
holder.getResponse().sendRedirect("/doesntmatter");
|
||||
assertEquals(SecurityContextHolder.getContext(), request.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY));
|
||||
assertTrue(((SaveContextOnUpdateOrErrorResponseWrapper)holder.getResponse()).isContextSaved());
|
||||
repo.saveContext(SecurityContextHolder.getContext(), holder.getRequest(), holder.getResponse());
|
||||
// Check it's still the same
|
||||
assertEquals(SecurityContextHolder.getContext(), request.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendErrorCausesEarlySaveOfContext() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContextHolder.setContext(repo.loadContext(holder));
|
||||
SecurityContextHolder.getContext().setAuthentication(testToken);
|
||||
holder.getResponse().sendError(404);
|
||||
assertEquals(SecurityContextHolder.getContext(), request.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY));
|
||||
assertTrue(((SaveContextOnUpdateOrErrorResponseWrapper)holder.getResponse()).isContextSaved());
|
||||
repo.saveContext(SecurityContextHolder.getContext(), holder.getRequest(), holder.getResponse());
|
||||
// Check it's still the same
|
||||
assertEquals(SecurityContextHolder.getContext(), request.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noSessionIsCreatedIfSessionWasInvalidatedDuringTheRequest() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.getSession();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContextHolder.setContext(repo.loadContext(holder));
|
||||
SecurityContextHolder.getContext().setAuthentication(testToken);
|
||||
request.getSession().invalidate();
|
||||
repo.saveContext(SecurityContextHolder.getContext(), holder.getRequest(), holder.getResponse());
|
||||
assertNull(request.getSession(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void settingCloneFromContextLoadsClonedContextObject() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
repo.setCloneFromHttpSession(true);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockContext contextBefore = new MockContext();
|
||||
request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, contextBefore);
|
||||
contextBefore.setAuthentication(testToken);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
|
||||
SecurityContext loadedContext = repo.loadContext(holder);
|
||||
assertTrue(loadedContext instanceof MockContext);
|
||||
assertFalse(loadedContext == contextBefore);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generateNewContextWorksWithContextClass() throws Exception {
|
||||
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
|
||||
repo.setSecurityContextClass(MockContext.class);
|
||||
assertTrue(repo.generateNewContext() instanceof MockContext);
|
||||
}
|
||||
|
||||
static class MockContext implements Cloneable, SecurityContext {
|
||||
Authentication a;
|
||||
|
||||
public Authentication getAuthentication() {
|
||||
return a;
|
||||
}
|
||||
|
||||
public void setAuthentication(Authentication authentication) {
|
||||
a = authentication;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
MockContext mc = new MockContext();
|
||||
mc.setAuthentication(this.getAuthentication());
|
||||
return mc;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package org.springframework.security.context;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.jmock.integration.junit4.JUnit4Mockery;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.providers.TestingAuthenticationToken;
|
||||
import org.springframework.security.ui.FilterChainOrder;
|
||||
|
||||
public class SecurityContextPersistenceFilterTests {
|
||||
Mockery jmock = new JUnit4Mockery();
|
||||
TestingAuthenticationToken testToken = new TestingAuthenticationToken("someone", "passwd", "ROLE_A");
|
||||
|
||||
@After
|
||||
public void clearContext() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextIsClearedAfterChainProceeds() throws Exception {
|
||||
final FilterChain chain = jmock.mock(FilterChain.class);
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
SecurityContextPersistenceFilter filter = new SecurityContextPersistenceFilter();
|
||||
SecurityContextHolder.getContext().setAuthentication(testToken);
|
||||
jmock.checking(new Expectations() {{
|
||||
oneOf(chain).doFilter(with(aNonNull(HttpServletRequest.class)), with(aNonNull(HttpServletResponse.class)));
|
||||
}});
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextIsStillClearedIfExceptionIsThrowByFilterChain() throws Exception {
|
||||
final FilterChain chain = jmock.mock(FilterChain.class);
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
SecurityContextPersistenceFilter filter = new SecurityContextPersistenceFilter();
|
||||
SecurityContextHolder.getContext().setAuthentication(testToken);
|
||||
|
||||
jmock.checking(new Expectations() {{
|
||||
oneOf(chain).doFilter(with(aNonNull(HttpServletRequest.class)), with(aNonNull(HttpServletResponse.class)));
|
||||
will(throwException(new IOException()));
|
||||
}});
|
||||
try {
|
||||
filter.doFilter(request, response, chain);
|
||||
fail();
|
||||
} catch(IOException expected) {
|
||||
}
|
||||
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadedContextContextIsCopiedToSecurityContextHolderAndUpdatedContextIsStored() throws Exception {
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
SecurityContextPersistenceFilter filter = new SecurityContextPersistenceFilter();
|
||||
final TestingAuthenticationToken beforeAuth = new TestingAuthenticationToken("someoneelse", "passwd", "ROLE_B");
|
||||
final SecurityContext scBefore = new SecurityContextImpl();
|
||||
final SecurityContext scExpectedAfter = new SecurityContextImpl();
|
||||
scExpectedAfter.setAuthentication(testToken);
|
||||
scBefore.setAuthentication(beforeAuth);
|
||||
final SecurityContextRepository repo = jmock.mock(SecurityContextRepository.class);
|
||||
filter.setSecurityContextRepository(repo);
|
||||
|
||||
jmock.checking(new Expectations() {{
|
||||
oneOf(repo).loadContext(with(aNonNull(HttpRequestResponseHolder.class))); will(returnValue(scBefore));
|
||||
oneOf(repo).saveContext(scExpectedAfter, request, response);
|
||||
}});
|
||||
|
||||
final FilterChain chain = new FilterChain() {
|
||||
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
|
||||
assertEquals(beforeAuth, SecurityContextHolder.getContext().getAuthentication());
|
||||
// Change the context here
|
||||
SecurityContextHolder.setContext(scExpectedAfter);
|
||||
}
|
||||
};
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
jmock.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterIsOnlyAppliedOncePerRequest() throws Exception {
|
||||
final FilterChain chain = jmock.mock(FilterChain.class);
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
SecurityContextPersistenceFilter filter = new SecurityContextPersistenceFilter();
|
||||
final SecurityContextRepository repo = jmock.mock(SecurityContextRepository.class);
|
||||
filter.setSecurityContextRepository(repo);
|
||||
final SecurityContext sc = SecurityContextHolder.getContext();
|
||||
|
||||
jmock.checking(new Expectations() {{
|
||||
oneOf(repo).loadContext(with(aNonNull(HttpRequestResponseHolder.class))); will(returnValue(sc));
|
||||
oneOf(repo).saveContext(sc, request, response);
|
||||
exactly(2).of(chain).doFilter(request, response);
|
||||
}});
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
assertNotNull(request.getAttribute(SecurityContextPersistenceFilter.FILTER_APPLIED));
|
||||
filter.doFilter(request, response, chain);
|
||||
jmock.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sessionIsEagerlyCreatedWhenConfigured() throws Exception {
|
||||
final FilterChain chain = jmock.mock(FilterChain.class);
|
||||
jmock.checking(new Expectations() {{ ignoring(chain); }});
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
SecurityContextPersistenceFilter filter = new SecurityContextPersistenceFilter();
|
||||
filter.setForceEagerSessionCreation(true);
|
||||
filter.doFilter(request, response, chain);
|
||||
assertNotNull(request.getSession(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterOrderHasExpectedValue() throws Exception {
|
||||
assertEquals(FilterChainOrder.SECURITY_CONTEXT_FILTER, (new SecurityContextPersistenceFilter()).getOrder());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user