This commit is contained in:
Luke Taylor 2008-12-02 12:49:13 +00:00
parent 7505b734d6
commit f3387cd879
2 changed files with 66 additions and 95 deletions

View File

@ -24,13 +24,17 @@ import org.aspectj.lang.JoinPoint;
/**
* Provides security interception of AspectJ method invocations.<p>The <code>ObjectDefinitionSource</code> required
* by this security interceptor is of type {@link MethodDefinitionSource}. This is shared with the AOP Alliance based
* security interceptor (<code>MethodSecurityInterceptor</code>), since both work with Java <code>Method</code>s.</p>
* <p>The secure object type is <code>org.aspectj.lang.JoinPoint</code>, which is passed from the relevant
* Provides security interception of AspectJ method invocations.
* <p>
* The <code>ObjectDefinitionSource</code> required by this security interceptor is of type
* {@link MethodDefinitionSource}. This is shared with the AOP Alliance based security interceptor
* (<code>MethodSecurityInterceptor</code>), since both work with Java <code>Method</code>s.
* <p>
* The secure object type is <code>org.aspectj.lang.JoinPoint</code>, which is passed from the relevant
* <code>around()</code> advice. The <code>around()</code> advice also passes an anonymous implementation of {@link
* AspectJCallback} which contains the call for AspectJ to continue processing: <code>return proceed();</code>.</p>
* <P>Refer to {@link AbstractSecurityInterceptor} for details on the workflow.</p>
* AspectJCallback} which contains the call for AspectJ to continue processing: <code>return proceed();</code>.
* <p>
* Refer to {@link AbstractSecurityInterceptor} for details on the workflow.
*
* @author Ben Alex
* @version $Id$
@ -42,10 +46,6 @@ public class AspectJSecurityInterceptor extends AbstractSecurityInterceptor {
//~ Methods ========================================================================================================
public MethodDefinitionSource getObjectDefinitionSource() {
return this.objectDefinitionSource;
}
public Class<? extends Object> getSecureObjectClass() {
return JoinPoint.class;
}

View File

@ -15,26 +15,26 @@
package org.springframework.security.intercept.method.aspectj;
import static org.junit.Assert.*;
import java.lang.reflect.Method;
import java.util.List;
import org.aspectj.lang.JoinPoint;
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.security.AccessDecisionManager;
import org.springframework.security.AccessDeniedException;
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.AuthenticationManager;
import org.springframework.security.ITargetObject;
import org.springframework.security.MockJoinPoint;
import org.springframework.security.MockRunAsManager;
import org.springframework.security.SecurityConfig;
import org.springframework.security.TargetObject;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.intercept.method.MapBasedMethodDefinitionSource;
import org.springframework.security.intercept.method.MethodDefinitionSourceEditor;
import org.springframework.security.intercept.method.MethodDefinitionSource;
import org.springframework.security.providers.TestingAuthenticationToken;
import org.springframework.security.util.AuthorityUtils;
/**
@ -44,93 +44,64 @@ import org.springframework.security.util.AuthorityUtils;
* @version $Id$
*/
public class AspectJSecurityInterceptorTests {
private Mockery jmock = new JUnit4Mockery();
private TestingAuthenticationToken token;
private AspectJSecurityInterceptor interceptor;
private AccessDecisionManager adm;
private MethodDefinitionSource mds;
private AuthenticationManager authman;
private AspectJCallback aspectJCallback;
private JoinPoint joinPoint;
//~ Methods ========================================================================================================
@Before
public final void setUp() throws Exception {
SecurityContextHolder.clearContext();
token = new TestingAuthenticationToken("Test", "Password");
interceptor = new AspectJSecurityInterceptor();
adm = jmock.mock(AccessDecisionManager.class);
authman = jmock.mock(AuthenticationManager.class);
mds = jmock.mock(MethodDefinitionSource.class);
interceptor.setAccessDecisionManager(adm);
interceptor.setAuthenticationManager(authman);
interceptor.setObjectDefinitionSource(mds);
Method method = TargetObject.class.getMethod("countLength", new Class[] {String.class});
joinPoint = new MockJoinPoint(new TargetObject(), method);
aspectJCallback = jmock.mock(AspectJCallback.class);
}
@After
public void clearContext() {
SecurityContextHolder.clearContext();
}
@Test
public void testCallbackIsInvokedWhenPermissionGranted() throws Exception {
AspectJSecurityInterceptor si = new AspectJSecurityInterceptor();
si.setApplicationEventPublisher(new MockApplicationEventPublisher(true));
si.setAccessDecisionManager(new MockAccessDecisionManager());
si.setAuthenticationManager(new MockAuthenticationManager());
si.setRunAsManager(new MockRunAsManager());
public void callbackIsInvokedWhenPermissionGranted() throws Exception {
jmock.checking(new Expectations() {{
oneOf(mds).getAttributes(with(any(JoinPoint.class))); will (returnValue(SecurityConfig.createList("ROLE_USER")));
oneOf(authman).authenticate(token); will(returnValue(token));
oneOf(adm).decide(with(token), with(aNonNull(JoinPoint.class)), with(aNonNull(List.class)));
oneOf(aspectJCallback).proceedWithObject();
}});
MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor();
editor.setAsText("org.springframework.security.TargetObject.countLength=MOCK_ONE,MOCK_TWO");
MapBasedMethodDefinitionSource map = (MapBasedMethodDefinitionSource) editor.getValue();
si.setObjectDefinitionSource(map);
assertEquals(map, si.getObjectDefinitionSource());
si.afterPropertiesSet();
Class<TargetObject> clazz = TargetObject.class;
Method method = clazz.getMethod("countLength", new Class[] {String.class});
MockJoinPoint joinPoint = new MockJoinPoint(new TargetObject(), method);
MockAspectJCallback aspectJCallback = new MockAspectJCallback();
SecurityContextHolder.getContext()
.setAuthentication(new TestingAuthenticationToken("rod", "koala",
new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_ONE")}));
Object result = si.invoke(joinPoint, aspectJCallback);
assertEquals("object proceeded", result);
SecurityContextHolder.getContext().setAuthentication(token);
interceptor.invoke(joinPoint, aspectJCallback);
jmock.assertIsSatisfied();
}
@Test(expected=AccessDeniedException.class)
public void testCallbackIsNotInvokedWhenPermissionDenied() throws Exception {
AspectJSecurityInterceptor si = new AspectJSecurityInterceptor();
si.setApplicationEventPublisher(new MockApplicationEventPublisher(true));
si.setAccessDecisionManager(new MockAccessDecisionManager());
si.setAuthenticationManager(new MockAuthenticationManager());
si.setRunAsManager(new MockRunAsManager());
public void callbackIsNotInvokedWhenPermissionDenied() throws Exception {
jmock.checking(new Expectations() {{
oneOf(mds).getAttributes(with(any(JoinPoint.class))); will (returnValue(SecurityConfig.createList("ROLE_USER")));
oneOf(authman).authenticate(token); will(returnValue(token));
oneOf(adm).decide(with(token), with(aNonNull(JoinPoint.class)), with(aNonNull(List.class)));
will(throwException(new AccessDeniedException("denied")));
never(aspectJCallback).proceedWithObject();
}});
MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor();
editor.setAsText("org.springframework.security.TargetObject.countLength=MOCK_ONE,MOCK_TWO");
MapBasedMethodDefinitionSource map = (MapBasedMethodDefinitionSource) editor.getValue();
si.setObjectDefinitionSource(map);
si.afterPropertiesSet();
Class<TargetObject> clazz = TargetObject.class;
Method method = clazz.getMethod("countLength", new Class[] {String.class});
MockJoinPoint joinPoint = new MockJoinPoint(new TargetObject(), method);
MockAspectJCallback aspectJCallback = new MockAspectJCallback();
aspectJCallback.setThrowExceptionIfInvoked(true);
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("rod", "koala", AuthorityUtils.NO_AUTHORITIES ));
si.invoke(joinPoint, aspectJCallback);
fail("Should have thrown AccessDeniedException");
}
//~ Inner Classes ==================================================================================================
private class MockAspectJCallback implements AspectJCallback {
private boolean throwExceptionIfInvoked = false;
private MockAspectJCallback() {}
public Object proceedWithObject() {
if (throwExceptionIfInvoked) {
throw new IllegalStateException("AspectJCallback proceeded");
}
return "object proceeded";
}
public void setThrowExceptionIfInvoked(boolean throwExceptionIfInvoked) {
this.throwExceptionIfInvoked = throwExceptionIfInvoked;
}
SecurityContextHolder.getContext().setAuthentication(token);
interceptor.invoke(joinPoint, aspectJCallback);
jmock.assertIsSatisfied();
}
}