SEC-1665: Add extra check of non-public declared methods in MethodInvocationAdapter, if public method cannot be found.
This commit is contained in:
parent
dc73bbef3f
commit
fd1a70edc2
|
@ -28,6 +28,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter;
|
import org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter;
|
||||||
import org.springframework.security.access.prepost.PrePostAnnotationSecurityMetadataSource;
|
import org.springframework.security.access.prepost.PrePostAnnotationSecurityMetadataSource;
|
||||||
import org.springframework.security.access.vote.AffirmativeBased;
|
import org.springframework.security.access.vote.AffirmativeBased;
|
||||||
|
import org.springframework.security.access.vote.RoleVoter;
|
||||||
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
|
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
|
@ -39,18 +40,23 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
* @since 3.0.3
|
* @since 3.0.3
|
||||||
*/
|
*/
|
||||||
public class AnnotationSecurityAspectTests {
|
public class AnnotationSecurityAspectTests {
|
||||||
private @Mock AccessDecisionManager adm;
|
private AffirmativeBased adm;
|
||||||
private @Mock AuthenticationManager authman;
|
private @Mock AuthenticationManager authman;
|
||||||
private TestingAuthenticationToken anne = new TestingAuthenticationToken("anne", "", "ROLE_A");
|
private TestingAuthenticationToken anne = new TestingAuthenticationToken("anne", "", "ROLE_A");
|
||||||
// private TestingAuthenticationToken bob = new TestingAuthenticationToken("bob", "", "ROLE_B");
|
// private TestingAuthenticationToken bob = new TestingAuthenticationToken("bob", "", "ROLE_B");
|
||||||
private AspectJMethodSecurityInterceptor interceptor;
|
private AspectJMethodSecurityInterceptor interceptor;
|
||||||
private SecuredImpl secured = new SecuredImpl();
|
private SecuredImpl secured = new SecuredImpl();
|
||||||
|
private SecuredImplSubclass securedSub = new SecuredImplSubclass();
|
||||||
private PrePostSecured prePostSecured = new PrePostSecured();
|
private PrePostSecured prePostSecured = new PrePostSecured();
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public final void setUp() throws Exception {
|
public final void setUp() throws Exception {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
interceptor = new AspectJMethodSecurityInterceptor();
|
interceptor = new AspectJMethodSecurityInterceptor();
|
||||||
|
adm = new AffirmativeBased();
|
||||||
|
AccessDecisionVoter[] voters = new AccessDecisionVoter[]
|
||||||
|
{new RoleVoter(), new PreInvocationAuthorizationAdviceVoter(new ExpressionBasedPreInvocationAdvice())};
|
||||||
|
adm.setDecisionVoters(Arrays.asList(voters));
|
||||||
interceptor.setAccessDecisionManager(adm);
|
interceptor.setAccessDecisionManager(adm);
|
||||||
interceptor.setAuthenticationManager(authman);
|
interceptor.setAuthenticationManager(authman);
|
||||||
interceptor.setSecurityMetadataSource(new SecuredAnnotationSecurityMetadataSource());
|
interceptor.setSecurityMetadataSource(new SecuredAnnotationSecurityMetadataSource());
|
||||||
|
@ -79,6 +85,31 @@ public class AnnotationSecurityAspectTests {
|
||||||
secured.securedClassMethod();
|
secured.securedClassMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected=AccessDeniedException.class)
|
||||||
|
public void internalPrivateCallIsIntercepted() {
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(anne);
|
||||||
|
|
||||||
|
try {
|
||||||
|
secured.publicCallsPrivate();
|
||||||
|
fail("Expected AccessDeniedException");
|
||||||
|
} catch (AccessDeniedException expected) {
|
||||||
|
}
|
||||||
|
securedSub.publicCallsPrivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=AccessDeniedException.class)
|
||||||
|
public void protectedMethodIsIntercepted() throws Exception {
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(anne);
|
||||||
|
|
||||||
|
secured.protectedMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void overriddenProtectedMethodIsNotIntercepted() throws Exception {
|
||||||
|
// AspectJ doesn't inherit annotations
|
||||||
|
securedSub.protectedMethod();
|
||||||
|
}
|
||||||
|
|
||||||
// SEC-1262
|
// SEC-1262
|
||||||
@Test(expected=AccessDeniedException.class)
|
@Test(expected=AccessDeniedException.class)
|
||||||
public void denyAllPreAuthorizeDeniesAccess() throws Exception {
|
public void denyAllPreAuthorizeDeniesAccess() throws Exception {
|
||||||
|
@ -101,10 +132,6 @@ public class AnnotationSecurityAspectTests {
|
||||||
DefaultMethodSecurityExpressionHandler eh = new DefaultMethodSecurityExpressionHandler();
|
DefaultMethodSecurityExpressionHandler eh = new DefaultMethodSecurityExpressionHandler();
|
||||||
interceptor.setSecurityMetadataSource(new PrePostAnnotationSecurityMetadataSource(
|
interceptor.setSecurityMetadataSource(new PrePostAnnotationSecurityMetadataSource(
|
||||||
new ExpressionBasedAnnotationAttributeFactory(eh)));
|
new ExpressionBasedAnnotationAttributeFactory(eh)));
|
||||||
AffirmativeBased adm = new AffirmativeBased();
|
|
||||||
AccessDecisionVoter[] voters = new AccessDecisionVoter[]
|
|
||||||
{new PreInvocationAuthorizationAdviceVoter(new ExpressionBasedPreInvocationAdvice())};
|
|
||||||
adm.setDecisionVoters(Arrays.asList(voters));
|
|
||||||
interceptor.setAccessDecisionManager(adm);
|
interceptor.setAccessDecisionManager(adm);
|
||||||
AfterInvocationProviderManager aim = new AfterInvocationProviderManager();
|
AfterInvocationProviderManager aim = new AfterInvocationProviderManager();
|
||||||
aim.setProviders(Arrays.asList(new PostInvocationAdviceProvider(new ExpressionBasedPostInvocationAdvice(eh))));
|
aim.setProviders(Arrays.asList(new PostInvocationAdviceProvider(new ExpressionBasedPostInvocationAdvice(eh))));
|
||||||
|
@ -125,6 +152,28 @@ class SecuredImpl implements SecuredInterface {
|
||||||
@Secured("ROLE_A")
|
@Secured("ROLE_A")
|
||||||
public void securedClassMethod() {
|
public void securedClassMethod() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Secured("ROLE_X")
|
||||||
|
private void privateMethod() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Secured("ROLE_X")
|
||||||
|
protected void protectedMethod() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Secured("ROLE_X")
|
||||||
|
public void publicCallsPrivate() {
|
||||||
|
privateMethod();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SecuredImplSubclass extends SecuredImpl {
|
||||||
|
protected void protectedMethod() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void publicCallsPrivate() {
|
||||||
|
super.publicCallsPrivate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PrePostSecured {
|
class PrePostSecured {
|
||||||
|
|
|
@ -32,11 +32,31 @@ public final class MethodInvocationAdapter implements MethodInvocation {
|
||||||
}
|
}
|
||||||
String targetMethodName = jp.getStaticPart().getSignature().getName();
|
String targetMethodName = jp.getStaticPart().getSignature().getName();
|
||||||
Class<?>[] types = ((CodeSignature) jp.getStaticPart().getSignature()).getParameterTypes();
|
Class<?>[] types = ((CodeSignature) jp.getStaticPart().getSignature()).getParameterTypes();
|
||||||
Class<?> declaringType = ((CodeSignature) jp.getStaticPart().getSignature()).getDeclaringType();
|
Class<?> declaringType = jp.getStaticPart().getSignature().getDeclaringType();
|
||||||
|
|
||||||
method = ClassUtils.getMethodIfAvailable(declaringType, targetMethodName, types);
|
method = findMethod(targetMethodName, declaringType, types);
|
||||||
Assert.notNull(method, "Could not obtain target method from JoinPoint: '"+ jp + "'");
|
|
||||||
|
|
||||||
|
if(method == null) {
|
||||||
|
throw new IllegalArgumentException("Could not obtain target method from JoinPoint: '"+ jp + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Method findMethod(String name, Class<?> declaringType, Class<?>[] params) {
|
||||||
|
Method method = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
method = declaringType.getMethod(name, params);
|
||||||
|
} catch (NoSuchMethodException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method == null) {
|
||||||
|
try {
|
||||||
|
method = declaringType.getDeclaredMethod(name, params);
|
||||||
|
} catch (NoSuchMethodException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Method getMethod() {
|
public Method getMethod() {
|
||||||
|
|
Loading…
Reference in New Issue