|
@@ -15,36 +15,27 @@
|
|
|
|
|
|
package org.springframework.security.intercept.web;
|
|
|
|
|
|
-import java.io.IOException;
|
|
|
-import java.util.Collection;
|
|
|
-import java.util.LinkedHashMap;
|
|
|
import java.util.List;
|
|
|
|
|
|
import javax.servlet.FilterChain;
|
|
|
-import javax.servlet.ServletException;
|
|
|
-import javax.servlet.ServletRequest;
|
|
|
-import javax.servlet.ServletResponse;
|
|
|
-
|
|
|
-import junit.framework.TestCase;
|
|
|
|
|
|
+import org.jmock.Expectations;
|
|
|
+import org.jmock.Mockery;
|
|
|
+import org.jmock.integration.junit4.JUnit4Mockery;
|
|
|
+import org.junit.After;
|
|
|
+import org.junit.Before;
|
|
|
+import org.junit.Test;
|
|
|
import org.springframework.mock.web.MockHttpServletRequest;
|
|
|
import org.springframework.mock.web.MockHttpServletResponse;
|
|
|
import org.springframework.security.AccessDecisionManager;
|
|
|
-import org.springframework.security.AccessDeniedException;
|
|
|
import org.springframework.security.Authentication;
|
|
|
+import org.springframework.security.AuthenticationManager;
|
|
|
import org.springframework.security.ConfigAttribute;
|
|
|
-import org.springframework.security.GrantedAuthority;
|
|
|
-import org.springframework.security.GrantedAuthorityImpl;
|
|
|
-import org.springframework.security.MockAccessDecisionManager;
|
|
|
import org.springframework.security.MockApplicationEventPublisher;
|
|
|
-import org.springframework.security.MockAuthenticationManager;
|
|
|
-import org.springframework.security.MockRunAsManager;
|
|
|
import org.springframework.security.RunAsManager;
|
|
|
import org.springframework.security.SecurityConfig;
|
|
|
import org.springframework.security.context.SecurityContextHolder;
|
|
|
-import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
|
|
-import org.springframework.security.util.AntUrlPathMatcher;
|
|
|
-import org.springframework.security.util.RegexUrlPathMatcher;
|
|
|
+import org.springframework.security.providers.TestingAuthenticationToken;
|
|
|
|
|
|
|
|
|
/**
|
|
@@ -53,235 +44,82 @@ import org.springframework.security.util.RegexUrlPathMatcher;
|
|
|
* @author Ben Alex
|
|
|
* @version $Id$
|
|
|
*/
|
|
|
-public class FilterSecurityInterceptorTests extends TestCase {
|
|
|
- //~ Constructors ===================================================================================================
|
|
|
-
|
|
|
- public FilterSecurityInterceptorTests() {
|
|
|
- }
|
|
|
+public class FilterSecurityInterceptorTests {
|
|
|
+ private Mockery jmock = new JUnit4Mockery();
|
|
|
+ private AuthenticationManager am;
|
|
|
+ private AccessDecisionManager adm;
|
|
|
+ private FilterInvocationDefinitionSource ods;
|
|
|
+ private RunAsManager ram;
|
|
|
+ private FilterSecurityInterceptor interceptor;
|
|
|
|
|
|
- public FilterSecurityInterceptorTests(String arg0) {
|
|
|
- super(arg0);
|
|
|
- }
|
|
|
|
|
|
//~ Methods ========================================================================================================
|
|
|
|
|
|
+ @Before
|
|
|
public final void setUp() throws Exception {
|
|
|
- super.setUp();
|
|
|
+ interceptor = new FilterSecurityInterceptor();
|
|
|
+ am = jmock.mock(AuthenticationManager.class);
|
|
|
+ ods = jmock.mock(FilterInvocationDefinitionSource.class);
|
|
|
+ adm = jmock.mock(AccessDecisionManager.class);
|
|
|
+ ram = jmock.mock(RunAsManager.class);
|
|
|
+ interceptor.setAuthenticationManager(am);
|
|
|
+ interceptor.setObjectDefinitionSource(ods);
|
|
|
+ interceptor.setAccessDecisionManager(adm);
|
|
|
+ interceptor.setRunAsManager(ram);
|
|
|
+ interceptor.setApplicationEventPublisher(new MockApplicationEventPublisher(true));
|
|
|
SecurityContextHolder.clearContext();
|
|
|
}
|
|
|
|
|
|
- protected void tearDown() throws Exception {
|
|
|
- super.tearDown();
|
|
|
+ @After
|
|
|
+ public void tearDown() throws Exception {
|
|
|
SecurityContextHolder.clearContext();
|
|
|
}
|
|
|
|
|
|
+ @Test(expected=IllegalArgumentException.class)
|
|
|
public void testEnsuresAccessDecisionManagerSupportsFilterInvocationClass() throws Exception {
|
|
|
- FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
|
|
|
- interceptor.setAuthenticationManager(new MockAuthenticationManager());
|
|
|
- interceptor.setObjectDefinitionSource(new DefaultFilterInvocationDefinitionSource(new RegexUrlPathMatcher()));
|
|
|
- interceptor.setRunAsManager(new MockRunAsManager());
|
|
|
-
|
|
|
- interceptor.setAccessDecisionManager(new AccessDecisionManager() {
|
|
|
- public boolean supports(Class clazz) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- public boolean supports(ConfigAttribute attribute) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- public void decide(Authentication authentication, Object object, List<ConfigAttribute> configAttributes)
|
|
|
- throws AccessDeniedException {
|
|
|
- throw new UnsupportedOperationException("mock method not implemented");
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- try {
|
|
|
- interceptor.afterPropertiesSet();
|
|
|
- fail("Should have thrown IllegalArgumentException");
|
|
|
- } catch (IllegalArgumentException expected) {
|
|
|
- assertEquals("AccessDecisionManager does not support secure object class: class org.springframework.security.intercept.web.FilterInvocation",
|
|
|
- expected.getMessage());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void testEnsuresRunAsManagerSupportsFilterInvocationClass()
|
|
|
- throws Exception {
|
|
|
- FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
|
|
|
- interceptor.setAccessDecisionManager(new MockAccessDecisionManager());
|
|
|
- interceptor.setAuthenticationManager(new MockAuthenticationManager());
|
|
|
- interceptor.setObjectDefinitionSource(new DefaultFilterInvocationDefinitionSource(new RegexUrlPathMatcher()));
|
|
|
-
|
|
|
- interceptor.setRunAsManager(new RunAsManager() {
|
|
|
- public boolean supports(Class clazz) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- public boolean supports(ConfigAttribute attribute) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- public Authentication buildRunAs(Authentication authentication, Object object,
|
|
|
- List<ConfigAttribute> config) {
|
|
|
- throw new UnsupportedOperationException("mock method not implemented");
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- try {
|
|
|
- interceptor.afterPropertiesSet();
|
|
|
- fail("Should have thrown IllegalArgumentException");
|
|
|
- } catch (IllegalArgumentException expected) {
|
|
|
- assertEquals("RunAsManager does not support secure object class: class org.springframework.security.intercept.web.FilterInvocation",
|
|
|
- expected.getMessage());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void testHttpsInvocationReflectsPortNumber() throws Throwable {
|
|
|
- // Setup the FilterSecurityInterceptor
|
|
|
- FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
|
|
|
- interceptor.setAccessDecisionManager(new MockAccessDecisionManager());
|
|
|
- interceptor.setAuthenticationManager(new MockAuthenticationManager());
|
|
|
- interceptor.setRunAsManager(new MockRunAsManager());
|
|
|
- interceptor.setApplicationEventPublisher(new MockApplicationEventPublisher(true));
|
|
|
-
|
|
|
- // Setup a mock config attribute definition
|
|
|
- MockFilterInvocationDefinitionMap mockSource = new MockFilterInvocationDefinitionMap("/secure/page.html", "MOCK_OK");
|
|
|
- interceptor.setObjectDefinitionSource(mockSource);
|
|
|
-
|
|
|
- // Setup our expectation that the filter chain will be invoked, as access is granted
|
|
|
- MockFilterChain chain = new MockFilterChain(true);
|
|
|
-
|
|
|
- // Setup our HTTPS request and response
|
|
|
- MockHttpServletResponse response = new MockHttpServletResponse();
|
|
|
- MockHttpServletRequest request = new MockHttpServletRequest();
|
|
|
- request.setServletPath("/secure/page.html");
|
|
|
- request.setScheme("https");
|
|
|
- request.setServerPort(443);
|
|
|
-
|
|
|
- // Setup a Context
|
|
|
- UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
|
|
|
- new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_OK")});
|
|
|
- SecurityContextHolder.getContext().setAuthentication(token);
|
|
|
-
|
|
|
- // Create and test our secure object
|
|
|
- FilterInvocation fi = new FilterInvocation(request, response, chain);
|
|
|
- interceptor.invoke(fi);
|
|
|
+ jmock.checking(new Expectations() {{
|
|
|
+ ignoring(ods);
|
|
|
+ allowing(adm).supports(FilterInvocation.class); will(returnValue(false));
|
|
|
+ }});
|
|
|
+ interceptor.afterPropertiesSet();
|
|
|
}
|
|
|
|
|
|
- public void testNormalStartupAndGetter() throws Exception {
|
|
|
- FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
|
|
|
- interceptor.setAccessDecisionManager(new MockAccessDecisionManager());
|
|
|
- interceptor.setAuthenticationManager(new MockAuthenticationManager());
|
|
|
-
|
|
|
- DefaultFilterInvocationDefinitionSource fidp =
|
|
|
- new DefaultFilterInvocationDefinitionSource(new RegexUrlPathMatcher());
|
|
|
- interceptor.setObjectDefinitionSource(fidp);
|
|
|
- interceptor.setRunAsManager(new MockRunAsManager());
|
|
|
+ @Test(expected=IllegalArgumentException.class)
|
|
|
+ public void testEnsuresRunAsManagerSupportsFilterInvocationClass() throws Exception {
|
|
|
+ jmock.checking(new Expectations() {{
|
|
|
+ ignoring(ods);
|
|
|
+ allowing(ram).supports(FilterInvocation.class); will(returnValue(false));
|
|
|
+ }});
|
|
|
interceptor.afterPropertiesSet();
|
|
|
- assertTrue(true);
|
|
|
- assertEquals(fidp, interceptor.getObjectDefinitionSource());
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * We just test invocation works in a success event. There is no need to test access denied events as the
|
|
|
+ * We just test invocation works in a success event. There is no need to test access denied events as the
|
|
|
* abstract parent enforces that logic, which is extensively tested separately.
|
|
|
- *
|
|
|
*/
|
|
|
+ @Test
|
|
|
public void testSuccessfulInvocation() throws Throwable {
|
|
|
- // Setup the FilterSecurityInterceptor
|
|
|
- FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
|
|
|
- interceptor.setAccessDecisionManager(new MockAccessDecisionManager());
|
|
|
- interceptor.setAuthenticationManager(new MockAuthenticationManager());
|
|
|
- interceptor.setRunAsManager(new MockRunAsManager());
|
|
|
- interceptor.setApplicationEventPublisher(new MockApplicationEventPublisher(true));
|
|
|
-
|
|
|
- // Setup a mock config attribute definition
|
|
|
- MockFilterInvocationDefinitionMap mockSource = new MockFilterInvocationDefinitionMap("/secure/page.html", "MOCK_OK");
|
|
|
- interceptor.setObjectDefinitionSource(mockSource);
|
|
|
-
|
|
|
- // Setup our expectation that the filter chain will be invoked, as access is granted
|
|
|
- MockFilterChain chain = new MockFilterChain(true);
|
|
|
-
|
|
|
- // Setup our HTTP request and response
|
|
|
- MockHttpServletResponse response = new MockHttpServletResponse();
|
|
|
- MockHttpServletRequest request = new MockHttpServletRequest();
|
|
|
+ final MockHttpServletResponse response = new MockHttpServletResponse();
|
|
|
+ final MockHttpServletRequest request = new MockHttpServletRequest();
|
|
|
request.setServletPath("/secure/page.html");
|
|
|
|
|
|
// Setup a Context
|
|
|
- UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
|
|
|
- new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_OK")});
|
|
|
+ final Authentication token = new TestingAuthenticationToken("Test", "Password", "NOT_USED");
|
|
|
SecurityContextHolder.getContext().setAuthentication(token);
|
|
|
|
|
|
// Create and test our secure object
|
|
|
- FilterInvocation fi = new FilterInvocation(request, response, chain);
|
|
|
- interceptor.invoke(fi);
|
|
|
- }
|
|
|
-
|
|
|
- public void testNotLoadedFromApplicationContext() throws Exception {
|
|
|
- LinkedHashMap reqMap = new LinkedHashMap();
|
|
|
- reqMap.put(new RequestKey("/secure/**", null), SecurityConfig.createList("ROLE_USER"));
|
|
|
- DefaultFilterInvocationDefinitionSource fids
|
|
|
- = new DefaultFilterInvocationDefinitionSource(new AntUrlPathMatcher(), reqMap);
|
|
|
-
|
|
|
- FilterSecurityInterceptor filter = new FilterSecurityInterceptor();
|
|
|
- filter.setObjectDefinitionSource(fids);
|
|
|
-
|
|
|
- MockFilterChain filterChain = new MockFilterChain();
|
|
|
- filterChain.expectToProceed = true;
|
|
|
-
|
|
|
- FilterInvocation fi = new FilterInvocation(
|
|
|
- new MockHttpServletRequest(), new MockHttpServletResponse(), filterChain);
|
|
|
- filter.invoke(fi);
|
|
|
- }
|
|
|
-
|
|
|
- //~ Inner Classes ==================================================================================================
|
|
|
-
|
|
|
- private class MockFilterChain implements FilterChain {
|
|
|
- private boolean expectToProceed;
|
|
|
-
|
|
|
- public MockFilterChain(boolean expectToProceed) {
|
|
|
- this.expectToProceed = expectToProceed;
|
|
|
- }
|
|
|
-
|
|
|
- private MockFilterChain() {
|
|
|
- }
|
|
|
-
|
|
|
- public void doFilter(ServletRequest request, ServletResponse response)
|
|
|
- throws IOException, ServletException {
|
|
|
- if (expectToProceed) {
|
|
|
- assertTrue(true);
|
|
|
- } else {
|
|
|
- fail("Did not expect filter chain to proceed");
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ final FilterChain chain = jmock.mock(FilterChain.class);
|
|
|
+ final FilterInvocation fi = new FilterInvocation(request, response, chain);
|
|
|
+ final List<ConfigAttribute> attributes = SecurityConfig.createList("MOCK_OK");
|
|
|
+
|
|
|
+ jmock.checking(new Expectations() {{
|
|
|
+ ignoring(ram);
|
|
|
+ allowing(ods).getAttributes(fi); will(returnValue(attributes));
|
|
|
+ oneOf(adm).decide(token, fi, attributes);
|
|
|
+ // Setup our expectation that the filter chain will be invoked, as access is granted
|
|
|
+ oneOf(chain).doFilter(request, response);
|
|
|
+ }});
|
|
|
|
|
|
- private class MockFilterInvocationDefinitionMap implements FilterInvocationDefinitionSource {
|
|
|
- private List<ConfigAttribute> toReturn;
|
|
|
- private String servletPath;
|
|
|
-
|
|
|
- public MockFilterInvocationDefinitionMap(String servletPath, String... toReturn) {
|
|
|
- this.servletPath = servletPath;
|
|
|
- this.toReturn = SecurityConfig.createList(toReturn);
|
|
|
- }
|
|
|
-
|
|
|
- public List<ConfigAttribute> getAttributes(Object object)
|
|
|
- throws IllegalArgumentException {
|
|
|
- FilterInvocation fi = (FilterInvocation) object;
|
|
|
-
|
|
|
- if (servletPath.equals(fi.getHttpRequest().getServletPath())) {
|
|
|
- return toReturn;
|
|
|
- } else {
|
|
|
- return null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public Collection<List<? extends ConfigAttribute>> getAllConfigAttributes() {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- public boolean supports(Class clazz) {
|
|
|
- return true;
|
|
|
- }
|
|
|
+ interceptor.invoke(fi);
|
|
|
}
|
|
|
}
|