1
0
mirror of synced 2026-08-05 17:57:15 +00:00

SEC-1001: Move core tiger code into core and adjust pom files

This commit is contained in:
Luke Taylor
2008-10-03 15:23:31 +00:00
parent ad4b5c487f
commit 7cc0965383
62 changed files with 82 additions and 540 deletions
@@ -0,0 +1,76 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.annotation.security.DenyAll;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.security.ConfigAttributeDefinition;
import org.springframework.security.intercept.method.AbstractFallbackMethodDefinitionSource;
/**
* Sources method security metadata from major JSR 250 security annotations.
*
* @author Ben Alex
* @version $Id$
* @since 2.0
*/
public class Jsr250MethodDefinitionSource extends AbstractFallbackMethodDefinitionSource {
protected ConfigAttributeDefinition findAttributes(Class clazz) {
return processAnnotations(clazz.getAnnotations());
}
protected ConfigAttributeDefinition findAttributes(Method method, Class targetClass) {
return processAnnotations(AnnotationUtils.getAnnotations(method));
}
public Collection getConfigAttributeDefinitions() {
return null;
}
private ConfigAttributeDefinition processAnnotations(Annotation[] annotations) {
if (annotations == null || annotations.length == 0) {
return null;
}
for (Annotation a: annotations) {
if (a instanceof DenyAll) {
return new ConfigAttributeDefinition(Jsr250SecurityConfig.DENY_ALL_ATTRIBUTE);
}
if (a instanceof PermitAll) {
return new ConfigAttributeDefinition(Jsr250SecurityConfig.PERMIT_ALL_ATTRIBUTE);
}
if (a instanceof RolesAllowed) {
RolesAllowed ra = (RolesAllowed) a;
List attributes = new ArrayList();
for (String allowed : ra.value()) {
attributes.add(new Jsr250SecurityConfig(allowed));
}
return new ConfigAttributeDefinition(attributes);
}
}
return null;
}
}
@@ -0,0 +1,22 @@
package org.springframework.security.annotation;
import org.springframework.security.SecurityConfig;
import javax.annotation.security.PermitAll;
import javax.annotation.security.DenyAll;
/**
* Security config applicable as a JSR 250 annotation attribute.
*
* @author Ryan Heaton
* @since 2.0
*/
public class Jsr250SecurityConfig extends SecurityConfig {
public static final Jsr250SecurityConfig PERMIT_ALL_ATTRIBUTE = new Jsr250SecurityConfig(PermitAll.class.getName());
public static final Jsr250SecurityConfig DENY_ALL_ATTRIBUTE = new Jsr250SecurityConfig(DenyAll.class.getName());
public Jsr250SecurityConfig(String role) {
super(role);
}
}
@@ -0,0 +1,77 @@
package org.springframework.security.annotation;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.ConfigAttribute;
import org.springframework.security.ConfigAttributeDefinition;
import org.springframework.security.Authentication;
import org.springframework.security.vote.AccessDecisionVoter;
import java.util.Iterator;
/**
* Voter on JSR-250 configuration attributes.
*
* @author Ryan Heaton
* @since 2.0
*/
public class Jsr250Voter implements AccessDecisionVoter {
/**
* The specified config attribute is supported if its an instance of a {@link Jsr250SecurityConfig}.
*
* @param configAttribute The config attribute.
* @return whether the config attribute is supported.
*/
public boolean supports(ConfigAttribute configAttribute) {
return configAttribute instanceof Jsr250SecurityConfig;
}
/**
* All classes are supported.
*
* @param clazz the class.
* @return true
*/
public boolean supports(Class clazz) {
return true;
}
/**
* Votes according to JSR 250.
*
* @param authentication The authentication object.
* @param object The access object.
* @param definition The configuration definition.
* @return The vote.
*/
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition definition) {
int result = ACCESS_ABSTAIN;
Iterator iter = definition.getConfigAttributes().iterator();
while (iter.hasNext()) {
ConfigAttribute attribute = (ConfigAttribute) iter.next();
if (Jsr250SecurityConfig.PERMIT_ALL_ATTRIBUTE.equals(attribute)) {
return ACCESS_GRANTED;
}
if (Jsr250SecurityConfig.DENY_ALL_ATTRIBUTE.equals(attribute)) {
return ACCESS_DENIED;
}
if (supports(attribute)) {
result = ACCESS_DENIED;
// Attempt to find a matching granted authority
for (GrantedAuthority authority : authentication.getAuthorities()) {
if (attribute.getAttribute().equals(authority.getAuthority())) {
return ACCESS_GRANTED;
}
}
}
}
return result;
}
}
@@ -0,0 +1,56 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Java 5 annotation for describing service layer security attributes.
*
* <p>The <code>Secured</code> annotation is used to define a list of security
* configuration attributes for business methods. This annotation can be used
* as a Java 5 alternative to XML configuration.
* <p>For example:
* <pre>
* &#64;Secured ({"ROLE_USER"})
* public void create(Contact contact);
*
* &#64;Secured ({"ROLE_USER", "ROLE_ADMIN"})
* public void update(Contact contact);
*
* &#64;Secured ({"ROLE_ADMIN"})
* public void delete(Contact contact);
* </pre>
* @author Mark St.Godard
* @version $Id$
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Secured {
/**
* Returns the list of security configuration attributes.
* (i.e. ROLE_USER, ROLE_ADMIN etc.)
* @return String[] The secure method attributes
*/
public String[] value();
}
@@ -0,0 +1,54 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Collection;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.security.ConfigAttributeDefinition;
import org.springframework.security.intercept.method.AbstractFallbackMethodDefinitionSource;
/**
* Sources method security metadata from Spring Security's {@link Secured} annotation.
*
* @author Ben Alex
* @version $Id$
*/
public class SecuredMethodDefinitionSource extends AbstractFallbackMethodDefinitionSource {
protected ConfigAttributeDefinition findAttributes(Class clazz) {
return processAnnotation(clazz.getAnnotation(Secured.class));
}
protected ConfigAttributeDefinition findAttributes(Method method, Class targetClass) {
return processAnnotation(AnnotationUtils.findAnnotation(method, Secured.class));
}
public Collection getConfigAttributeDefinitions() {
return null;
}
private ConfigAttributeDefinition processAnnotation(Annotation a) {
if (a == null || !(a instanceof Secured)) {
return null;
}
Secured secured = (Secured) a;
return new ConfigAttributeDefinition(secured.value());
}
}
@@ -0,0 +1,48 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.annotation;
import javax.annotation.security.RolesAllowed;
import javax.annotation.security.PermitAll;
/**
* @version $Id$
*/
@Secured({"ROLE_USER"})
@PermitAll
public interface BusinessService {
//~ Methods ========================================================================================================
@Secured({"ROLE_ADMIN"})
@RolesAllowed({"ROLE_ADMIN"})
public void someAdminMethod();
@Secured({"ROLE_USER", "ROLE_ADMIN"})
@RolesAllowed({"ROLE_USER", "ROLE_ADMIN"})
public void someUserAndAdminMethod();
@Secured({"ROLE_USER"})
@RolesAllowed({"ROLE_USER"})
public void someUserMethod1();
@Secured({"ROLE_USER"})
@RolesAllowed({"ROLE_USER"})
public void someUserMethod2();
public int someOther(String s);
public int someOther(int input);
}
@@ -0,0 +1,36 @@
package org.springframework.security.annotation;
/**
*
* @author Joe Scalise
*/
public class BusinessServiceImpl<E extends Entity> implements BusinessService {
@Secured({"ROLE_USER"})
public void someUserMethod1() {
}
@Secured({"ROLE_USER"})
public void someUserMethod2() {
}
@Secured({"ROLE_USER", "ROLE_ADMIN"})
public void someUserAndAdminMethod() {
}
@Secured({"ROLE_ADMIN"})
public void someAdminMethod() {
}
public E someUserMethod3(final E entity) {
return entity;
}
public int someOther(String s) {
return 0;
}
public int someOther(int input) {
return input;
}
}
@@ -0,0 +1,28 @@
package org.springframework.security.annotation;
/**
*
* @author Joe Scalise
*/
public class Department extends Entity {
//~ Instance fields ========================================================
private boolean active = true;
//~ Constructors ===========================================================
public Department(String name) {
super(name);
}
//~ Methods ================================================================
public boolean isActive() {
return this.active;
}
void deactive() {
this.active = true;
}
}
@@ -0,0 +1,11 @@
package org.springframework.security.annotation;
/**
*
* @author Joe Scalise
*/
public interface DepartmentService extends BusinessService {
@Secured({"ROLE_USER"})
Department someUserMethod3(Department dept);
}
@@ -0,0 +1,12 @@
package org.springframework.security.annotation;
/**
* @author Joe Scalise
*/
public class DepartmentServiceImpl extends BusinessServiceImpl <Department> implements DepartmentService {
@Secured({"ROLE_ADMIN"})
public Department someUserMethod3(final Department dept) {
return super.someUserMethod3(dept);
}
}
@@ -0,0 +1,11 @@
package org.springframework.security.annotation;
/**
* Class to act as a superclass for annotations testing.
*
* @author Ben Alex
*
*/
public class Entity {
public Entity(String someParameter) {}
}
@@ -0,0 +1,37 @@
package org.springframework.security.annotation;
import javax.annotation.security.RolesAllowed;
import javax.annotation.security.PermitAll;
/**
*
* @author Luke Taylor
* @version $Id$
*/
@PermitAll
public class Jsr250BusinessServiceImpl implements BusinessService {
@RolesAllowed("ROLE_USER")
public void someUserMethod1() {
}
@RolesAllowed("ROLE_USER")
public void someUserMethod2() {
}
@RolesAllowed({"ROLE_USER", "ROLE_ADMIN"})
public void someUserAndAdminMethod() {
}
@RolesAllowed("ROLE_ADMIN")
public void someAdminMethod() {
}
public int someOther(String input) {
return 0;
}
public int someOther(int input) {
return input;
}
}
@@ -0,0 +1,104 @@
package org.springframework.security.annotation;
import static org.junit.Assert.assertEquals;
import javax.annotation.security.DenyAll;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import junit.framework.Assert;
import org.junit.Test;
import org.springframework.security.ConfigAttributeDefinition;
/**
* @author Luke Taylor
* @author Ben Alex
* @version $Id$
*/
public class Jsr250MethodDefinitionSourceTests {
Jsr250MethodDefinitionSource mds = new Jsr250MethodDefinitionSource();
A a = new A();
UserAllowedClass userAllowed = new UserAllowedClass();
DenyAllClass denyAll = new DenyAllClass();
@Test
public void methodWithRolesAllowedHasCorrectAttribute() throws Exception {
ConfigAttributeDefinition accessAttributes = mds.findAttributes(a.getClass().getMethod("adminMethod"), null);
assertEquals(1, accessAttributes.getConfigAttributes().size());
assertEquals("ADMIN", accessAttributes.getConfigAttributes().iterator().next().toString());
}
@Test
public void permitAllMethodHasPermitAllAttribute() throws Exception {
ConfigAttributeDefinition accessAttributes = mds.findAttributes(a.getClass().getMethod("permitAllMethod"), null);
assertEquals(1, accessAttributes.getConfigAttributes().size());
assertEquals("javax.annotation.security.PermitAll", accessAttributes.getConfigAttributes().iterator().next().toString());
}
@Test
public void noRoleMethodHasDenyAllAttributeWithDenyAllClass() throws Exception {
ConfigAttributeDefinition accessAttributes = mds.findAttributes(denyAll.getClass());
assertEquals(1, accessAttributes.getConfigAttributes().size());
assertEquals("javax.annotation.security.DenyAll", accessAttributes.getConfigAttributes().iterator().next().toString());
}
@Test
public void adminMethodHasAdminAttributeWithDenyAllClass() throws Exception {
ConfigAttributeDefinition accessAttributes = mds.findAttributes(denyAll.getClass().getMethod("adminMethod"), null);
assertEquals(1, accessAttributes.getConfigAttributes().size());
assertEquals("ADMIN", accessAttributes.getConfigAttributes().iterator().next().toString());
}
@Test
public void noRoleMethodHasNoAttributes() throws Exception {
ConfigAttributeDefinition accessAttributes = mds.findAttributes(a.getClass().getMethod("noRoleMethod"), null);
Assert.assertNull(accessAttributes);
}
@Test
public void classRoleIsAppliedToNoRoleMethod() throws Exception {
ConfigAttributeDefinition accessAttributes = mds.findAttributes(userAllowed.getClass().getMethod("noRoleMethod"), null);
Assert.assertNull(accessAttributes);
}
@Test
public void methodRoleOverridesClassRole() throws Exception {
ConfigAttributeDefinition accessAttributes = mds.findAttributes(userAllowed.getClass().getMethod("adminMethod"), null);
assertEquals(1, accessAttributes.getConfigAttributes().size());
assertEquals("ADMIN", accessAttributes.getConfigAttributes().iterator().next().toString());
}
//~ Inner Classes ======================================================================================================
public static class A {
public void noRoleMethod() {}
@RolesAllowed("ADMIN")
public void adminMethod() {}
@PermitAll
public void permitAllMethod() {}
}
@RolesAllowed("USER")
public static class UserAllowedClass {
public void noRoleMethod() {}
@RolesAllowed("ADMIN")
public void adminMethod() {}
}
@DenyAll
public static class DenyAllClass {
public void noRoleMethod() {}
@RolesAllowed("ADMIN")
public void adminMethod() {}
}
}
@@ -0,0 +1,111 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import junit.framework.TestCase;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.security.ConfigAttributeDefinition;
import org.springframework.security.annotation.test.Entity;
import org.springframework.security.annotation.test.PersonServiceImpl;
import org.springframework.security.annotation.test.Service;
import org.springframework.security.intercept.method.MapBasedMethodDefinitionSource;
import org.springframework.security.intercept.method.MethodDefinitionSourceEditor;
/**
* Extra tests to demonstrate generics behaviour with <code>MapBasedMethodDefinitionSource</code>.
*
* @author Ben Alex
* @version $Id$
*/
public class MethodDefinitionSourceEditorTigerTests extends TestCase {
//~ Methods ========================================================================================================
public void testConcreteClassInvocations() throws Exception {
MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor();
editor.setAsText(
"org.springframework.security.annotation.test.Service.makeLower*=ROLE_FROM_INTERFACE\r\n" +
"org.springframework.security.annotation.test.Service.makeUpper*=ROLE_FROM_INTERFACE\r\n" +
"org.springframework.security.annotation.test.ServiceImpl.makeUpper*=ROLE_FROM_IMPLEMENTATION");
MapBasedMethodDefinitionSource map = (MapBasedMethodDefinitionSource) editor.getValue();
assertEquals(3, map.getMethodMapSize());
ConfigAttributeDefinition returnedMakeLower = map.getAttributes(new MockMethodInvocation(Service.class,
"makeLowerCase", new Class[]{Entity.class}, new PersonServiceImpl()));
ConfigAttributeDefinition expectedMakeLower = new ConfigAttributeDefinition("ROLE_FROM_INTERFACE");
assertEquals(expectedMakeLower, returnedMakeLower);
ConfigAttributeDefinition returnedMakeUpper = map.getAttributes(new MockMethodInvocation(Service.class,
"makeUpperCase", new Class[]{Entity.class}, new PersonServiceImpl()));
ConfigAttributeDefinition expectedMakeUpper = new ConfigAttributeDefinition(new String[]{"ROLE_FROM_IMPLEMENTATION"});
assertEquals(expectedMakeUpper, returnedMakeUpper);
}
public void testBridgeMethodResolution() throws Exception {
MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor();
editor.setAsText(
"org.springframework.security.annotation.test.PersonService.makeUpper*=ROLE_FROM_INTERFACE\r\n" +
"org.springframework.security.annotation.test.ServiceImpl.makeUpper*=ROLE_FROM_ABSTRACT\r\n" +
"org.springframework.security.annotation.test.PersonServiceImpl.makeUpper*=ROLE_FROM_PSI");
MapBasedMethodDefinitionSource map = (MapBasedMethodDefinitionSource) editor.getValue();
assertEquals(3, map.getMethodMapSize());
ConfigAttributeDefinition returnedMakeUpper = map.getAttributes(new MockMethodInvocation(Service.class,
"makeUpperCase", new Class[]{Entity.class}, new PersonServiceImpl()));
ConfigAttributeDefinition expectedMakeUpper = new ConfigAttributeDefinition(new String[]{"ROLE_FROM_PSI"});
assertEquals(expectedMakeUpper, returnedMakeUpper);
}
//~ Inner Classes ==================================================================================================
private class MockMethodInvocation implements MethodInvocation {
private Method method;
private Object targetObject;
public MockMethodInvocation(Class clazz, String methodName, Class[] parameterTypes, Object targetObject)
throws NoSuchMethodException {
this.method = clazz.getMethod(methodName, parameterTypes);
this.targetObject = targetObject;
}
public Object[] getArguments() {
return null;
}
public Method getMethod() {
return method;
}
public AccessibleObject getStaticPart() {
return null;
}
public Object getThis() {
return targetObject;
}
public Object proceed() throws Throwable {
return null;
}
}
}
@@ -0,0 +1,149 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.annotation;
import java.lang.reflect.Method;
import junit.framework.TestCase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.ConfigAttributeDefinition;
import org.springframework.security.SecurityConfig;
import org.springframework.util.StringUtils;
/**
* Tests for {@link org.springframework.security.annotation.SecuredMethodDefinitionSource}
*
* @author Mark St.Godard
* @author Joe Scalise
* @author Ben Alex
* @version $Id$
*/
public class SecuredMethodDefinitionSourceTests extends TestCase {
//~ Instance fields ================================================================================================
private SecuredMethodDefinitionSource mds = new SecuredMethodDefinitionSource();;
private Log logger = LogFactory.getLog(SecuredMethodDefinitionSourceTests.class);
//~ Methods ========================================================================================================
public void testGenericsSuperclassDeclarationsAreIncludedWhenSubclassesOverride() {
Method method = null;
try {
method = DepartmentServiceImpl.class.getMethod("someUserMethod3", new Class[] {Department.class});
} catch (NoSuchMethodException unexpected) {
fail("Should be a superMethod called 'someUserMethod3' on class!");
}
ConfigAttributeDefinition attrs = this.mds.findAttributes(method, DepartmentServiceImpl.class);
assertNotNull(attrs);
if (logger.isDebugEnabled()) {
logger.debug("attrs: " + StringUtils.collectionToCommaDelimitedString(attrs.getConfigAttributes()));
}
// expect 1 attribute
assertTrue("Did not find 1 attribute", attrs.getConfigAttributes().size() == 1);
// should have 1 SecurityConfig
for (Object obj : attrs.getConfigAttributes()) {
assertTrue(obj instanceof SecurityConfig);
SecurityConfig sc = (SecurityConfig) obj;
assertEquals("Found an incorrect role", "ROLE_ADMIN", sc.getAttribute());
}
Method superMethod = null;
try {
superMethod = DepartmentServiceImpl.class.getMethod("someUserMethod3", new Class[] {Entity.class});
} catch (NoSuchMethodException unexpected) {
fail("Should be a superMethod called 'someUserMethod3' on class!");
}
ConfigAttributeDefinition superAttrs = this.mds.findAttributes(superMethod, DepartmentServiceImpl.class);
assertNotNull(superAttrs);
if (logger.isDebugEnabled()) {
logger.debug("superAttrs: " + StringUtils.collectionToCommaDelimitedString(superAttrs.getConfigAttributes()));
}
// This part of the test relates to SEC-274
// expect 1 attribute
assertTrue("Did not find 1 attribute", superAttrs.getConfigAttributes().size() == 1);
// should have 1 SecurityConfig
for (Object obj : superAttrs.getConfigAttributes()) {
assertTrue(obj instanceof SecurityConfig);
SecurityConfig sc = (SecurityConfig) obj;
assertEquals("Found an incorrect role", "ROLE_ADMIN", sc.getAttribute());
}
}
public void testGetAttributesClass() {
ConfigAttributeDefinition attrs = this.mds.findAttributes(BusinessService.class);
assertNotNull(attrs);
// expect 1 annotation
assertTrue(attrs.getConfigAttributes().size() == 1);
// should have 1 SecurityConfig
SecurityConfig sc = (SecurityConfig) attrs.getConfigAttributes().iterator().next();
assertTrue(sc.getAttribute().equals("ROLE_USER"));
}
public void testGetAttributesMethod() {
Method method = null;
try {
method = BusinessService.class.getMethod("someUserAndAdminMethod", new Class[] {});
} catch (NoSuchMethodException unexpected) {
fail("Should be a method called 'someUserAndAdminMethod' on class!");
}
ConfigAttributeDefinition attrs = this.mds.findAttributes(method, BusinessService.class);
assertNotNull(attrs);
// expect 2 attributes
assertTrue(attrs.getConfigAttributes().size() == 2);
boolean user = false;
boolean admin = false;
// should have 2 SecurityConfigs
for (Object obj : attrs.getConfigAttributes()) {
assertTrue(obj instanceof SecurityConfig);
SecurityConfig sc = (SecurityConfig) obj;
if (sc.getAttribute().equals("ROLE_USER")) {
user = true;
} else if (sc.getAttribute().equals("ROLE_ADMIN")) {
admin = true;
}
}
// expect to have ROLE_USER and ROLE_ADMIN
assertTrue(user && admin);
}
}
@@ -0,0 +1,52 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.annotation.test;
import org.springframework.util.Assert;
/**
* An entity used in our generics testing.
*
* @author Ben Alex
* @version $Id$
*/
public class Entity {
//~ Instance fields ================================================================================================
String info;
//~ Constructors ===================================================================================================
public Entity(String info) {
Assert.hasText(info, "Some information must be given!");
this.info = info;
}
//~ Methods ========================================================================================================
public String getInfo() {
return info;
}
void makeLowercase() {
this.info = info.toLowerCase();
}
void makeUppercase() {
this.info = info.toUpperCase();
}
}
@@ -0,0 +1,44 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.annotation.test;
/**
* An extended version of <code>Entity</code>.
*
* @author Ben Alex
* @version $Id$
*/
public class Organisation extends Entity {
//~ Instance fields ================================================================================================
private boolean active = true;
//~ Constructors ===================================================================================================
public Organisation(String name) {
super(name);
}
//~ Methods ========================================================================================================
void deactive() {
this.active = true;
}
public boolean isActive() {
return this.active;
}
}
@@ -0,0 +1,28 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.annotation.test;
/**
* DOCUMENT ME!
*
* @author $author$
* @version $Revision: 1496 $
*/
public interface OrganisationService extends Service<Organisation> {
//~ Methods ========================================================================================================
public void deactive(Organisation org);
}
@@ -0,0 +1,27 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.annotation.test;
/**
*
*/
public class OrganisationServiceImpl extends ServiceImpl<Organisation> implements OrganisationService {
//~ Methods ========================================================================================================
public void deactive(Organisation org) {
org.deactive();
}
}
@@ -0,0 +1,44 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.annotation.test;
/**
* An extended version of <code>Entity</code>.
*
* @author Ben Alex
* @version $Id$
*/
public class Person extends Entity {
//~ Instance fields ================================================================================================
private boolean active = true;
//~ Constructors ===================================================================================================
public Person(String name) {
super(name);
}
//~ Methods ========================================================================================================
void deactive() {
this.active = true;
}
public boolean isActive() {
return this.active;
}
}
@@ -0,0 +1,25 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.annotation.test;
/**
*
*/
public interface PersonService extends Service<Person> {
//~ Methods ========================================================================================================
public void deactive(Person person);
}
@@ -0,0 +1,30 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.annotation.test;
/**
* DOCUMENT ME!
*
* @author $author$
* @version $Revision: 1496 $
*/
public class PersonServiceImpl extends ServiceImpl<Person> implements PersonService {
//~ Methods ========================================================================================================
public void deactive(Person person) {
person.deactive();
}
}
@@ -0,0 +1,37 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.annotation.test;
import java.util.Collection;
/**
* An interface that uses Java 5 generics.
*
* @author Ben Alex
* @version $Id$
*/
public interface Service<E extends Entity> {
//~ Methods ========================================================================================================
public int countElements(Collection<E> ids);
public void makeLowerCase(E input);
public void makeUpperCase(E input);
public void publicMakeLowerCase(E input);
}
@@ -0,0 +1,42 @@
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.annotation.test;
import java.util.Collection;
/**
*
*/
public class ServiceImpl<E extends Entity> implements Service<E> {
//~ Methods ========================================================================================================
public int countElements(Collection<E> ids) {
return 0;
}
public void makeLowerCase(E input) {
input.makeLowercase();
}
public void makeUpperCase(E input) {
input.makeUppercase();
}
public void publicMakeLowerCase(E input) {
input.makeUppercase();
}
}
@@ -0,0 +1,188 @@
package org.springframework.security.config;
import static org.junit.Assert.*;
import static org.springframework.security.config.ConfigTestUtils.*;
import org.junit.After;
import org.junit.Test;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.context.support.AbstractXmlApplicationContext;
import org.springframework.security.AccessDeniedException;
import org.springframework.security.AuthenticationCredentialsNotFoundException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.annotation.BusinessService;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.util.InMemoryXmlApplicationContext;
/**
* @author Ben Alex
* @author Luke Taylor
* @version $Id$
*/
public class GlobalMethodSecurityBeanDefinitionParserTests {
private AbstractXmlApplicationContext appContext;
private BusinessService target;
public void loadContext() {
setContext(
"<b:bean id='target' class='org.springframework.security.annotation.BusinessServiceImpl'/>" +
"<global-method-security>" +
" <protect-pointcut expression='execution(* *.someUser*(..))' access='ROLE_USER'/>" +
" <protect-pointcut expression='execution(* *.someAdmin*(..))' access='ROLE_ADMIN'/>" +
"</global-method-security>" + ConfigTestUtils.AUTH_PROVIDER_XML
);
target = (BusinessService) appContext.getBean("target");
}
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
appContext = null;
}
SecurityContextHolder.clearContext();
target = null;
}
@Test(expected=AuthenticationCredentialsNotFoundException.class)
public void targetShouldPreventProtectedMethodInvocationWithNoContext() {
loadContext();
target.someUserMethod1();
}
@Test
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() {
loadContext();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password");
SecurityContextHolder.getContext().setAuthentication(token);
target.someUserMethod1();
}
@Test(expected=AccessDeniedException.class)
public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() {
loadContext();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_SOMEOTHERROLE")});
SecurityContextHolder.getContext().setAuthentication(token);
target.someAdminMethod();
}
@Test
public void doesntInterfereWithBeanPostProcessing() {
setContext(
"<b:bean id='myUserService' class='org.springframework.security.config.PostProcessedMockUserDetailsService'/>" +
"<global-method-security />" +
"<authentication-provider user-service-ref='myUserService'/>" +
"<b:bean id='beanPostProcessor' class='org.springframework.security.config.MockUserServiceBeanPostProcessor'/>"
);
PostProcessedMockUserDetailsService service = (PostProcessedMockUserDetailsService)appContext.getBean("myUserService");
assertEquals("Hello from the post processor!", service.getPostProcessorWasHere());
}
@Test(expected=AccessDeniedException.class)
public void worksWithAspectJAutoproxy() {
setContext(
"<global-method-security>" +
" <protect-pointcut expression='execution(* org.springframework.security.config.*Service.*(..))'" +
" access='ROLE_SOMETHING' />" +
"</global-method-security>" +
"<b:bean id='myUserService' class='org.springframework.security.config.PostProcessedMockUserDetailsService'/>" +
"<aop:aspectj-autoproxy />" +
"<authentication-provider user-service-ref='myUserService'/>"
);
UserDetailsService service = (UserDetailsService) appContext.getBean("myUserService");
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_SOMEOTHERROLE")});
SecurityContextHolder.getContext().setAuthentication(token);
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(* org.springframework.security.annotation.BusinessService.someOther(String))' access='ROLE_ADMIN'/>" +
" <protect-pointcut expression='execution(* org.springframework.security.annotation.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), but should require ROLE_USER
target.someOther(0);
try {
// String version should required admin role
target.someOther("somestring");
fail("Expected AccessDeniedException");
} catch (AccessDeniedException expected) {
}
}
@Test
public void supportsBooleanPointcutExpressions() {
setContext(
"<b:bean id='target' class='org.springframework.security.annotation.BusinessServiceImpl'/>" +
"<global-method-security>" +
" <protect-pointcut expression=" +
" 'execution(* org.springframework.security.annotation.BusinessService.*(..)) " +
" and not execution(* org.springframework.security.annotation.BusinessService.someOther(String)))' " +
" access='ROLE_USER'/>" +
"</global-method-security>" + ConfigTestUtils.AUTH_PROVIDER_XML
);
target = (BusinessService) appContext.getBean("target");
// String method should not be protected
target.someOther("somestring");
// All others should require ROLE_USER
try {
target.someOther(0);
fail("Expected AuthenticationCredentialsNotFoundException");
} catch (AuthenticationCredentialsNotFoundException expected) {
}
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("user", "password"));
target.someOther(0);
}
@Test(expected=BeanDefinitionParsingException.class)
public void duplicateElementCausesError() {
setContext(
"<global-method-security />" +
"<global-method-security />"
);
}
@Test(expected=AccessDeniedException.class)
public void worksWithoutTargetOrClass() {
setContext(
"<global-method-security secured-annotations='enabled'/>" +
"<b:bean id='businessService' class='org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean'>" +
" <b:property name='serviceUrl' value='http://localhost:8080/SomeService'/>" +
" <b:property name='serviceInterface' value='org.springframework.security.annotation.BusinessService'/>" +
"</b:bean>" + AUTH_PROVIDER_XML
);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_SOMEOTHERROLE")});
SecurityContextHolder.getContext().setAuthentication(token);
target = (BusinessService) appContext.getBean("businessService");
target.someUserMethod1();
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
}
@@ -0,0 +1,72 @@
package org.springframework.security.config;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.security.AccessDeniedException;
import org.springframework.security.AuthenticationCredentialsNotFoundException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.annotation.BusinessService;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.util.InMemoryXmlApplicationContext;
/**
* @author Luke Taylor
* @version $Id$
*/
public class Jsr250AnnotationDrivenBeanDefinitionParserTests {
private InMemoryXmlApplicationContext appContext;
private BusinessService target;
@Before
public void loadContext() {
appContext = new InMemoryXmlApplicationContext(
"<b:bean id='target' class='org.springframework.security.annotation.Jsr250BusinessServiceImpl'/>" +
"<global-method-security jsr250-annotations='enabled'/>" + ConfigTestUtils.AUTH_PROVIDER_XML
);
target = (BusinessService) appContext.getBean("target");
}
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
}
SecurityContextHolder.clearContext();
}
@Test(expected=AuthenticationCredentialsNotFoundException.class)
public void targetShouldPreventProtectedMethodInvocationWithNoContext() {
target.someUserMethod1();
}
@Test
public void permitAllShouldBeDefaultAttribute() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_USER")});
SecurityContextHolder.getContext().setAuthentication(token);
target.someOther(0);
}
@Test
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_USER")});
SecurityContextHolder.getContext().setAuthentication(token);
target.someUserMethod1();
}
@Test(expected=AccessDeniedException.class)
public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_SOMEOTHERROLE")});
SecurityContextHolder.getContext().setAuthentication(token);
target.someAdminMethod();
}
}
@@ -0,0 +1,63 @@
package org.springframework.security.config;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.security.AccessDeniedException;
import org.springframework.security.AuthenticationCredentialsNotFoundException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.annotation.BusinessService;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.util.InMemoryXmlApplicationContext;
/**
* @author Ben Alex
* @version $Id$
*/
public class SecuredAnnotationDrivenBeanDefinitionParserTests {
private InMemoryXmlApplicationContext appContext;
private BusinessService target;
@Before
public void loadContext() {
appContext = new InMemoryXmlApplicationContext(
"<b:bean id='target' class='org.springframework.security.annotation.Jsr250BusinessServiceImpl'/>" +
"<global-method-security secured-annotations='enabled'/>" + ConfigTestUtils.AUTH_PROVIDER_XML
);
target = (BusinessService) appContext.getBean("target");
}
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
}
SecurityContextHolder.clearContext();
}
@Test(expected=AuthenticationCredentialsNotFoundException.class)
public void targetShouldPreventProtectedMethodInvocationWithNoContext() {
target.someUserMethod1();
}
@Test
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_USER")});
SecurityContextHolder.getContext().setAuthentication(token);
target.someUserMethod1();
}
@Test(expected=AccessDeniedException.class)
public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_SOMEOTHERROLE")});
SecurityContextHolder.getContext().setAuthentication(token);
target.someAdminMethod();
}
}