mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-27 06:12:27 +00:00
OPEN - issue SEC-905: <protect-pointcut /> pointcuts do not respect method arguments
http://jira.springframework.org/browse/SEC-905. Added extra registration method to MapBasedMethodDefinitionSource which takes a Method instance rather than the method name.
This commit is contained in:
parent
d9ab0758ee
commit
55d357f42d
@ -42,5 +42,7 @@ public interface BusinessService {
|
|||||||
@RolesAllowed({"ROLE_USER"})
|
@RolesAllowed({"ROLE_USER"})
|
||||||
public void someUserMethod2();
|
public void someUserMethod2();
|
||||||
|
|
||||||
|
public int someOther(String s);
|
||||||
|
|
||||||
public int someOther(int input);
|
public int someOther(int input);
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,10 @@ public class BusinessServiceImpl<E extends Entity> implements BusinessService {
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int someOther(String s) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public int someOther(int input) {
|
public int someOther(int input) {
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,10 @@ public class Jsr250BusinessServiceImpl implements BusinessService {
|
|||||||
public void someAdminMethod() {
|
public void someAdminMethod() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int someOther(String input) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public int someOther(int input) {
|
public int someOther(int input) {
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,21 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
|
|||||||
service.loadUserByUsername("notused");
|
service.loadUserByUsername("notused");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void supportsMethodArgumentsInPointcut() {
|
||||||
|
setContext(
|
||||||
|
"<b:bean id='target' class='org.springframework.security.annotation.BusinessServiceImpl'/>" +
|
||||||
|
"<global-method-security>" +
|
||||||
|
" <protect-pointcut expression='execution(* *.someOther(String))' access='ROLE_ADMIN'/>" +
|
||||||
|
" <protect-pointcut expression='execution(* *.BusinessService*(..))' access='ROLE_USER'/>" +
|
||||||
|
"</global-method-security>" + ConfigTestUtils.AUTH_PROVIDER_XML
|
||||||
|
);
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("user", "password"));
|
||||||
|
target = (BusinessService) appContext.getBean("target");
|
||||||
|
// someOther(int) should not be matched by someOther(String)
|
||||||
|
target.someOther(0);
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected=BeanDefinitionParsingException.class)
|
@Test(expected=BeanDefinitionParsingException.class)
|
||||||
public void duplicateElementCausesError() {
|
public void duplicateElementCausesError() {
|
||||||
setContext(
|
setContext(
|
||||||
|
@ -103,21 +103,6 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add configuration attributes for a secure method.
|
|
||||||
*
|
|
||||||
* @param method the method to be secured
|
|
||||||
* @param attr required authorities associated with the method
|
|
||||||
*/
|
|
||||||
private void addSecureMethod(RegisteredMethod method, ConfigAttributeDefinition attr) {
|
|
||||||
Assert.notNull(method, "RegisteredMethod required");
|
|
||||||
Assert.notNull(attr, "Configuration attribute required");
|
|
||||||
if (logger.isInfoEnabled()) {
|
|
||||||
logger.info("Adding secure method [" + method + "] with attributes [" + attr + "]");
|
|
||||||
}
|
|
||||||
this.methodMap.put(method, attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add configuration attributes for a secure method. Method names can end or start with <code>*</code>
|
* Add configuration attributes for a secure method. Method names can end or start with <code>*</code>
|
||||||
* for matching multiple methods.
|
* for matching multiple methods.
|
||||||
@ -192,6 +177,38 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds configuration attributes for a specific method, for example where the method has been
|
||||||
|
* matched using a pointcut expression. If a match already exists in the map for the method, then
|
||||||
|
* the existing match will be retained, so that if this method is called for a more general pointcut
|
||||||
|
* it will not override a more specific one which has already been added. This
|
||||||
|
*/
|
||||||
|
public void addSecureMethod(Class javaType, Method method, ConfigAttributeDefinition attr) {
|
||||||
|
RegisteredMethod key = new RegisteredMethod(method, javaType);
|
||||||
|
|
||||||
|
if (methodMap.containsKey(key)) {
|
||||||
|
logger.debug("Method [" + method + "] is already registered with attributes [" + methodMap.get(key) + "]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
methodMap.put(key, attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add configuration attributes for a secure method.
|
||||||
|
*
|
||||||
|
* @param method the method to be secured
|
||||||
|
* @param attr required authorities associated with the method
|
||||||
|
*/
|
||||||
|
private void addSecureMethod(RegisteredMethod method, ConfigAttributeDefinition attr) {
|
||||||
|
Assert.notNull(method, "RegisteredMethod required");
|
||||||
|
Assert.notNull(attr, "Configuration attribute required");
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
logger.info("Adding secure method [" + method + "] with attributes [" + attr + "]");
|
||||||
|
}
|
||||||
|
this.methodMap.put(method, attr);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains the configuration attributes explicitly defined against this bean.
|
* Obtains the configuration attributes explicitly defined against this bean.
|
||||||
*
|
*
|
||||||
|
@ -124,7 +124,7 @@ public final class ProtectPointcutPostProcessor implements BeanPostProcessor {
|
|||||||
logger.debug("AspectJ pointcut expression '" + expression.getPointcutExpression() + "' matches target class '" + targetClass.getName() + "' (bean ID '" + beanName + "') for method '" + method + "'; registering security configuration attribute '" + attr + "'");
|
logger.debug("AspectJ pointcut expression '" + expression.getPointcutExpression() + "' matches target class '" + targetClass.getName() + "' (bean ID '" + beanName + "') for method '" + method + "'; registering security configuration attribute '" + attr + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
mapBasedMethodDefinitionSource.addSecureMethod(targetClass, method.getName(), attr);
|
mapBasedMethodDefinitionSource.addSecureMethod(targetClass, method, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return matches;
|
return matches;
|
||||||
|
@ -6,9 +6,8 @@ public abstract class ConfigTestUtils {
|
|||||||
" <user-service id='us'>" +
|
" <user-service id='us'>" +
|
||||||
" <user name='bob' password='bobspassword' authorities='ROLE_A,ROLE_B' />" +
|
" <user name='bob' password='bobspassword' authorities='ROLE_A,ROLE_B' />" +
|
||||||
" <user name='bill' password='billspassword' authorities='ROLE_A,ROLE_B,AUTH_OTHER' />" +
|
" <user name='bill' password='billspassword' authorities='ROLE_A,ROLE_B,AUTH_OTHER' />" +
|
||||||
|
" <user name='admin' password='password' authorities='ROLE_ADMIN,ROLE_USER' />" +
|
||||||
|
" <user name='user' password='password' authorities='ROLE_USER' />" +
|
||||||
" </user-service>" +
|
" </user-service>" +
|
||||||
" </authentication-provider>";
|
" </authentication-provider>";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
package org.springframework.security.intercept.method;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.security.ConfigAttributeDefinition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link MapBasedMethodDefinitionSource}.
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @since 2.0.4
|
||||||
|
*/
|
||||||
|
public class MapBasedMethodDefinitionSourceTests {
|
||||||
|
private final ConfigAttributeDefinition ROLE_A = new ConfigAttributeDefinition("ROLE_A");
|
||||||
|
private final ConfigAttributeDefinition ROLE_B = new ConfigAttributeDefinition("ROLE_B");
|
||||||
|
private MapBasedMethodDefinitionSource mds;
|
||||||
|
private Method someMethodString;
|
||||||
|
private Method someMethodInteger;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void initialize() throws Exception {
|
||||||
|
mds = new MapBasedMethodDefinitionSource();
|
||||||
|
someMethodString = MockService.class.getMethod("someMethod", String.class);
|
||||||
|
someMethodInteger = MockService.class.getMethod("someMethod", Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void wildcardedMatchIsOverwrittenByMoreSpecificMatch() {
|
||||||
|
mds.addSecureMethod(MockService.class, "some*", ROLE_A);
|
||||||
|
mds.addSecureMethod(MockService.class, "someMethod*", ROLE_B);
|
||||||
|
assertEquals(ROLE_B, mds.getAttributes(someMethodInteger, MockService.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void methodsWithDifferentArgumentsAreMatchedCorrectly() throws Exception {
|
||||||
|
mds.addSecureMethod(MockService.class, someMethodInteger, ROLE_A);
|
||||||
|
mds.addSecureMethod(MockService.class, someMethodString, ROLE_B);
|
||||||
|
|
||||||
|
assertEquals(ROLE_A, mds.getAttributes(someMethodInteger, MockService.class));
|
||||||
|
assertEquals(ROLE_B, mds.getAttributes(someMethodString, MockService.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MockService {
|
||||||
|
public void someMethod(String s) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void someMethod(Integer i) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user