1
0
mirror of synced 2026-07-13 06:40:03 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
Luke Taylor d6d9bc9d6b [maven-release-plugin] copy for tag spring-security-parent-2.0.3 2008-06-23 14:08:17 +00:00
254 changed files with 3106 additions and 10763 deletions
+2 -8
View File
@@ -3,12 +3,13 @@
<parent>
<artifactId>spring-security-parent</artifactId>
<groupId>org.springframework.security</groupId>
<version>2.0.4</version>
<version>2.0.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-acl</artifactId>
<name>Spring Security - ACL module</name>
<version>2.0.3</version>
<packaging>bundle</packaging>
<dependencies>
@@ -24,13 +25,6 @@
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
@@ -0,0 +1,39 @@
package org.springframework.security.acls.domain;
import org.springframework.security.acls.Permission;
/**
* Provides an abstract base for standard {@link Permission} instances that wish to offer static convenience
* methods to callers via delegation to {@link DefaultPermissionFactory}.
*
* @author Ben Alex
* @since 2.0.3
*
*/
public abstract class AbstractRegisteredPermission extends AbstractPermission {
protected static DefaultPermissionFactory defaultPermissionFactory = new DefaultPermissionFactory();
protected AbstractRegisteredPermission(int mask, char code) {
super(mask, code);
}
protected final static void registerPermissionsFor(Class subClass) {
defaultPermissionFactory.registerPublicPermissions(subClass);
}
public final static Permission buildFromMask(int mask) {
return defaultPermissionFactory.buildFromMask(mask);
}
public final static Permission[] buildFromMask(int[] masks) {
return defaultPermissionFactory.buildFromMask(masks);
}
public final static Permission buildFromName(String name) {
return defaultPermissionFactory.buildFromName(name);
}
public final static Permission[] buildFromName(String[] names) {
return defaultPermissionFactory.buildFromName(names);
}
}
@@ -28,16 +28,14 @@ import org.springframework.security.acls.Permission;
* @author Ben Alex
* @version $Id$
*/
public class BasePermission extends AbstractPermission {
public class BasePermission extends AbstractRegisteredPermission {
public static final Permission READ = new BasePermission(1 << 0, 'R'); // 1
public static final Permission WRITE = new BasePermission(1 << 1, 'W'); // 2
public static final Permission CREATE = new BasePermission(1 << 2, 'C'); // 4
public static final Permission DELETE = new BasePermission(1 << 3, 'D'); // 8
public static final Permission ADMINISTRATION = new BasePermission(1 << 4, 'A'); // 16
protected static DefaultPermissionFactory defaultPermissionFactory = new DefaultPermissionFactory();
/**
/**
* Registers the public static permissions defined on this class. This is mandatory so
* that the static methods will operate correctly.
*/
@@ -48,25 +46,4 @@ public class BasePermission extends AbstractPermission {
protected BasePermission(int mask, char code) {
super(mask, code);
}
protected final static void registerPermissionsFor(Class subClass) {
defaultPermissionFactory.registerPublicPermissions(subClass);
}
public final static Permission buildFromMask(int mask) {
return defaultPermissionFactory.buildFromMask(mask);
}
public final static Permission[] buildFromMask(int[] masks) {
return defaultPermissionFactory.buildFromMask(masks);
}
public final static Permission buildFromName(String name) {
return defaultPermissionFactory.buildFromName(name);
}
public final static Permission[] buildFromName(String[] names) {
return defaultPermissionFactory.buildFromName(names);
}
}
}
@@ -18,14 +18,12 @@ import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import javax.sql.DataSource;
@@ -175,33 +173,14 @@ public final class BasicLookupStrategy implements LookupStrategy {
auditLogger, parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner());
// Copy the "aces" from the input to the destination
Field fieldAces = FieldUtils.getField(AclImpl.class, "aces");
Field fieldAcl = FieldUtils.getField(AccessControlEntryImpl.class, "acl");
Field field = FieldUtils.getField(AclImpl.class, "aces");
try {
fieldAces.setAccessible(true);
fieldAcl.setAccessible(true);
// Obtain the "aces" from the input ACL
Iterator i = ((List) fieldAces.get(inputAcl)).iterator();
// Create a list in which to store the "aces" for the "result" AclImpl instance
List acesNew = new ArrayList();
// Iterate over the "aces" input and replace each nested AccessControlEntryImpl.getAcl() with the new "result" AclImpl instance
// This ensures StubAclParent instances are removed, as per SEC-951
while(i.hasNext()) {
AccessControlEntryImpl ace = (AccessControlEntryImpl) i.next();
fieldAcl.set(ace, result);
acesNew.add(ace);
}
// Finally, now that the "aces" have been converted to have the "result" AclImpl instance, modify the "result" AclImpl instance
fieldAces.set(result, acesNew);
field.setAccessible(true);
field.set(result, field.get(inputAcl));
} catch (IllegalAccessException ex) {
throw new IllegalStateException("Could not obtain or set AclImpl or AccessControlEntryImpl fields");
throw new IllegalStateException("Could not obtain or set AclImpl.ace field");
}
return result;
}
@@ -32,12 +32,6 @@ public class PermissionTests {
//~ Methods ========================================================================================================
@Test
public void basePermissionTest() {
Permission p = BasePermission.buildFromName("WRITE");
assertNotNull(p);
}
@Test
public void expectedIntegerValues() {
assertEquals(1, BasePermission.READ.getMask());
@@ -53,7 +53,7 @@ public class SidTests extends TestCase {
}
try {
Authentication authentication = new TestingAuthenticationToken(null, "password");
Authentication authentication = new TestingAuthenticationToken(null, "password", null);
Sid principalSid = new PrincipalSid(authentication);
Assert.fail("It should have thrown IllegalArgumentException");
}
@@ -62,7 +62,7 @@ public class SidTests extends TestCase {
}
try {
Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
Authentication authentication = new TestingAuthenticationToken("johndoe", "password", null);
Sid principalSid = new PrincipalSid(authentication);
Assert.assertTrue(true);
}
@@ -128,15 +128,15 @@ public class SidTests extends TestCase {
}
public void testPrincipalSidEquals() throws Exception {
Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
Authentication authentication = new TestingAuthenticationToken("johndoe", "password", null);
Sid principalSid = new PrincipalSid(authentication);
Assert.assertFalse(principalSid.equals(null));
Assert.assertFalse(principalSid.equals("DIFFERENT_TYPE_OBJECT"));
Assert.assertTrue(principalSid.equals(principalSid));
Assert.assertTrue(principalSid.equals(new PrincipalSid(authentication)));
Assert.assertTrue(principalSid.equals(new PrincipalSid(new TestingAuthenticationToken("johndoe", null))));
Assert.assertFalse(principalSid.equals(new PrincipalSid(new TestingAuthenticationToken("scott", null))));
Assert.assertTrue(principalSid.equals(new PrincipalSid(new TestingAuthenticationToken("johndoe", null, null))));
Assert.assertFalse(principalSid.equals(new PrincipalSid(new TestingAuthenticationToken("scott", null, null))));
Assert.assertTrue(principalSid.equals(new PrincipalSid("johndoe")));
Assert.assertFalse(principalSid.equals(new PrincipalSid("scott")));
}
@@ -156,13 +156,14 @@ public class SidTests extends TestCase {
}
public void testPrincipalSidHashCode() throws Exception {
Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
Authentication authentication = new TestingAuthenticationToken("johndoe", "password", null);
Sid principalSid = new PrincipalSid(authentication);
Assert.assertTrue(principalSid.hashCode() == new String("johndoe").hashCode());
Assert.assertTrue(principalSid.hashCode() == new PrincipalSid("johndoe").hashCode());
Assert.assertTrue(principalSid.hashCode() != new PrincipalSid("scott").hashCode());
Assert.assertTrue(principalSid.hashCode() != new PrincipalSid(new TestingAuthenticationToken("scott", "password")).hashCode());
Assert.assertTrue(principalSid.hashCode() != new PrincipalSid(new TestingAuthenticationToken("scott", "password",
null)).hashCode());
}
public void testGrantedAuthoritySidHashCode() throws Exception {
@@ -176,7 +177,7 @@ public class SidTests extends TestCase {
}
public void testGetters() throws Exception {
Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
Authentication authentication = new TestingAuthenticationToken("johndoe", "password", null);
PrincipalSid principalSid = new PrincipalSid(authentication);
GrantedAuthority ga = new GrantedAuthorityImpl("ROLE_TEST");
GrantedAuthoritySid gaSid = new GrantedAuthoritySid(ga);
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-adapters</artifactId>
<version>2.0.4</version>
<version>2.0.3</version>
</parent>
<artifactId>spring-security-catalina</artifactId>
<name>Spring Security - Catalina adapter</name>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-adapters</artifactId>
<version>2.0.4</version>
<version>2.0.3</version>
</parent>
<artifactId>spring-security-jboss</artifactId>
<name>Spring Security - JBoss adapter</name>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-adapters</artifactId>
<version>2.0.4</version>
<version>2.0.3</version>
</parent>
<artifactId>spring-security-jetty</artifactId>
<name>Spring Security - Jetty adapter</name>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-parent</artifactId>
<version>2.0.4</version>
<version>2.0.3</version>
</parent>
<artifactId>spring-security-adapters</artifactId>
<name>Spring Security - Adapters</name>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-adapters</artifactId>
<version>2.0.4</version>
<version>2.0.3</version>
</parent>
<artifactId>spring-security-resin</artifactId>
<name>Spring Security - Resin adapter</name>
+1 -8
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-parent</artifactId>
<version>2.0.4</version>
<version>2.0.3</version>
</parent>
<artifactId>spring-security-cas-client</artifactId>
<name>Spring Security - CAS support</name>
@@ -15,13 +15,6 @@
<artifactId>spring-security-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-dao</artifactId>
+2 -7
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-parent</artifactId>
<version>2.0.4</version>
<version>2.0.3</version>
</parent>
<packaging>bundle</packaging>
<artifactId>spring-security-core-tiger</artifactId>
@@ -21,12 +21,7 @@
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-remoting</artifactId>
<scope>test</scope>
</dependency>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
@@ -39,10 +39,8 @@ public interface BusinessService {
public void someUserMethod1();
@Secured({"ROLE_USER"})
@RolesAllowed({"ROLE_USER"})
@RolesAllowed({"ROLE_USER"})
public void someUserMethod2();
public int someOther(String s);
public int someOther(int input);
}
@@ -26,11 +26,7 @@ public class BusinessServiceImpl<E extends Entity> implements BusinessService {
return entity;
}
public int someOther(String s) {
return 0;
}
public int someOther(int input) {
return input;
}
public int someOther(int input) {
return input;
}
}
@@ -27,11 +27,7 @@ public class Jsr250BusinessServiceImpl implements BusinessService {
public void someAdminMethod() {
}
public int someOther(String input) {
return 0;
}
public int someOther(int input) {
return input;
}
}
return input;
}
}
@@ -1,12 +1,13 @@
package org.springframework.security.config;
import static org.junit.Assert.*;
import static org.springframework.security.config.ConfigTestUtils.*;
import static org.junit.Assert.assertEquals;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.context.support.AbstractXmlApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.security.AccessDeniedException;
import org.springframework.security.AuthenticationCredentialsNotFoundException;
import org.springframework.security.GrantedAuthority;
@@ -14,12 +15,10 @@ 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 {
@@ -28,36 +27,29 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
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
);
appContext = new ClassPathXmlApplicationContext("org/springframework/security/config/global-method-security.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();
loadContext();
target.someUserMethod1();
}
@Test
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() {
loadContext();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password");
loadContext();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_USER")});
SecurityContextHolder.getContext().setAuthentication(token);
target.someUserMethod1();
@@ -65,19 +57,20 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
@Test(expected=AccessDeniedException.class)
public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() {
loadContext();
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 />" +
// "<http auto-config='true'/>" +
"<authentication-provider user-service-ref='myUserService'/>" +
"<b:bean id='beanPostProcessor' class='org.springframework.security.config.MockUserServiceBeanPostProcessor'/>"
);
@@ -86,75 +79,7 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
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(
@@ -162,27 +87,8 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
"<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);
}
}
@@ -3,6 +3,7 @@ package org.springframework.security.config;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.security.AccessDeniedException;
import org.springframework.security.AuthenticationCredentialsNotFoundException;
import org.springframework.security.GrantedAuthority;
@@ -10,23 +11,19 @@ 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 ClassPathXmlApplicationContext 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
);
appContext = new ClassPathXmlApplicationContext("/org/springframework/security/config/jsr250-annotated-method-security.xml");
target = (BusinessService) appContext.getBean("target");
}
@@ -51,7 +48,7 @@ public class Jsr250AnnotationDrivenBeanDefinitionParserTests {
target.someOther(0);
}
@Test
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
@@ -69,4 +66,4 @@ public class Jsr250AnnotationDrivenBeanDefinitionParserTests {
target.someAdminMethod();
}
}
}
@@ -3,6 +3,7 @@ package org.springframework.security.config;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.security.AccessDeniedException;
import org.springframework.security.AuthenticationCredentialsNotFoundException;
import org.springframework.security.GrantedAuthority;
@@ -10,23 +11,19 @@ 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 ClassPathXmlApplicationContext 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
);
appContext = new ClassPathXmlApplicationContext("org/springframework/security/config/secured-annotated-method-security.xml");
target = (BusinessService) appContext.getBean("target");
}
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns="http://www.springframework.org/schema/security"
xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
<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>
<authentication-provider>
<user-service>
<user name="bob" password="bobspassword" authorities="ROLE_A,ROLE_B" />
<user name="bill" password="billspassword" authorities="ROLE_A,ROLE_B,AUTH_OTHER" />
</user-service>
</authentication-provider>
</b:beans>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns="http://www.springframework.org/schema/security"
xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
<b:bean id="target" class="org.springframework.security.annotation.Jsr250BusinessServiceImpl"/>
<global-method-security jsr250-annotations="enabled"/>
<authentication-provider>
<user-service>
<user name="bob" password="bobspassword" authorities="ROLE_A,ROLE_B" />
<user name="bill" password="billspassword" authorities="ROLE_A,ROLE_B,AUTH_OTHER" />
</user-service>
</authentication-provider>
</b:beans>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns="http://www.springframework.org/schema/security"
xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
<b:bean id="target" class="org.springframework.security.annotation.Jsr250BusinessServiceImpl"/>
<global-method-security secured-annotations="enabled"/>
<authentication-provider>
<user-service>
<user name="bob" password="bobspassword" authorities="ROLE_A,ROLE_B" />
<user name="bill" password="billspassword" authorities="ROLE_A,ROLE_B,AUTH_OTHER" />
</user-service>
</authentication-provider>
</b:beans>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-parent</artifactId>
<version>2.0.4</version>
<version>2.0.3</version>
</parent>
<packaging>bundle</packaging>
<artifactId>spring-security-core</artifactId>
@@ -21,13 +21,8 @@ import org.springframework.util.Assert;
/**
* Basic concrete implementation of a {@link GrantedAuthority}.
*
* <p>
* Stores a <code>String</code> representation of an authority granted to the {@link Authentication} object.
* <p>
* If compared to a custom authority which returns null from {@link #getAuthority}, the <tt>compareTo</tt>
* method will return -1, so the custom authority will take precedence.
* Basic concrete implementation of a {@link GrantedAuthority}.<p>Stores a <code>String</code> representation of an
* authority granted to the {@link Authentication} object.</p>
*
* @author Ben Alex
* @version $Id$
@@ -41,6 +36,7 @@ public class GrantedAuthorityImpl implements GrantedAuthority, Serializable {
//~ Constructors ===================================================================================================
public GrantedAuthorityImpl(String role) {
super();
Assert.hasText(role, "A granted authority textual representation is required");
this.role = role;
}
@@ -75,13 +71,8 @@ public class GrantedAuthorityImpl implements GrantedAuthority, Serializable {
public int compareTo(Object o) {
if (o != null && o instanceof GrantedAuthority) {
String rhsRole = ((GrantedAuthority) o).getAuthority();
if (rhsRole == null) {
return -1;
}
return role.compareTo(rhsRole);
GrantedAuthority rhs = (GrantedAuthority) o;
return this.role.compareTo(rhs.getAuthority());
}
return -1;
}
@@ -1,167 +0,0 @@
package org.springframework.security.authoritymapping;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* <p>
* This class implements the Attributes2GrantedAuthoritiesMapper and
* MappableAttributesRetriever interfaces based on the supplied Map.
* It supports both one-to-one and one-to-many mappings. The granted
* authorities to map to can be supplied either as a String or as a
* GrantedAuthority object.
* </p>
* @author Ruud Senden
*/
public class MapBasedAttributes2GrantedAuthoritiesMapper implements Attributes2GrantedAuthoritiesMapper, MappableAttributesRetriever, InitializingBean {
private Map attributes2grantedAuthoritiesMap = null;
private String stringSeparator = ",";
private String[] mappableAttributes = null;
/**
* Check whether all properties have been set to correct values, and do some preprocessing.
*/
public void afterPropertiesSet() {
Assert.notEmpty(attributes2grantedAuthoritiesMap,"A non-empty attributes2grantedAuthoritiesMap must be supplied");
attributes2grantedAuthoritiesMap = preProcessMap(attributes2grantedAuthoritiesMap);
try {
mappableAttributes = (String[])attributes2grantedAuthoritiesMap.keySet().toArray(new String[]{});
} catch ( ArrayStoreException ase ) {
throw new IllegalArgumentException("attributes2grantedAuthoritiesMap contains non-String objects as keys");
}
}
/**
* Preprocess the given map
* @param orgMap The map to process
* @return the processed Map
*/
private Map preProcessMap(Map orgMap) {
Map result = new HashMap(orgMap.size());
Iterator it = orgMap.entrySet().iterator();
while ( it.hasNext() ) {
Map.Entry entry = (Map.Entry)it.next();
result.put(entry.getKey(),getGrantedAuthorityCollection(entry.getValue()));
}
return result;
}
/**
* Convert the given value to a collection of Granted Authorities
*
* @param value
* The value to convert to a GrantedAuthority Collection
* @return Collection containing the GrantedAuthority Collection
*/
private Collection getGrantedAuthorityCollection(Object value) {
Collection result = new ArrayList();
addGrantedAuthorityCollection(result,value);
return result;
}
/**
* Convert the given value to a collection of Granted Authorities,
* adding the result to the given result collection.
*
* @param value
* The value to convert to a GrantedAuthority Collection
* @return Collection containing the GrantedAuthority Collection
*/
private void addGrantedAuthorityCollection(Collection result, Object value) {
if ( value != null ) {
if ( value instanceof Collection ) {
addGrantedAuthorityCollection(result,(Collection)value);
} else if ( value instanceof Object[] ) {
addGrantedAuthorityCollection(result,(Object[])value);
} else if ( value instanceof String ) {
addGrantedAuthorityCollection(result,(String)value);
} else if ( value instanceof GrantedAuthority ) {
result.add(value);
} else {
throw new IllegalArgumentException("Invalid object type: "+value.getClass().getName());
}
}
}
private void addGrantedAuthorityCollection(Collection result, Collection value) {
Iterator it = value.iterator();
while ( it.hasNext() ) {
addGrantedAuthorityCollection(result,it.next());
}
}
private void addGrantedAuthorityCollection(Collection result, Object[] value) {
for ( int i = 0 ; i < value.length ; i++ ) {
addGrantedAuthorityCollection(result,value[i]);
}
}
private void addGrantedAuthorityCollection(Collection result, String value) {
StringTokenizer st = new StringTokenizer(value,stringSeparator,false);
while ( st.hasMoreTokens() ) {
String nextToken = st.nextToken();
if ( StringUtils.hasText(nextToken) ) {
result.add(new GrantedAuthorityImpl(nextToken));
}
}
}
/**
* Map the given array of attributes to Spring Security GrantedAuthorities.
*/
public GrantedAuthority[] getGrantedAuthorities(String[] attributes) {
List gaList = new ArrayList();
for (int i = 0; i < attributes.length; i++) {
Collection c = (Collection)attributes2grantedAuthoritiesMap.get(attributes[i]);
if ( c != null ) { gaList.addAll(c); }
}
GrantedAuthority[] result = new GrantedAuthority[gaList.size()];
result = (GrantedAuthority[])gaList.toArray(result);
return result;
}
/**
* @return Returns the attributes2grantedAuthoritiesMap.
*/
public Map getAttributes2grantedAuthoritiesMap() {
return attributes2grantedAuthoritiesMap;
}
/**
* @param attributes2grantedAuthoritiesMap The attributes2grantedAuthoritiesMap to set.
*/
public void setAttributes2grantedAuthoritiesMap(Map attributes2grantedAuthoritiesMap) {
this.attributes2grantedAuthoritiesMap = attributes2grantedAuthoritiesMap;
}
/**
*
* @see org.springframework.security.authoritymapping.MappableAttributesRetriever#getMappableAttributes()
*/
public String[] getMappableAttributes() {
return mappableAttributes;
}
/**
* @return Returns the stringSeparator.
*/
public String getStringSeparator() {
return stringSeparator;
}
/**
* @param stringSeparator The stringSeparator to set.
*/
public void setStringSeparator(String stringSeparator) {
this.stringSeparator = stringSeparator;
}
}
@@ -61,13 +61,14 @@ public class AnonymousBeanDefinitionParser implements BeanDefinitionParser {
filter.getPropertyValues().addPropertyValue("userAttribute", username + "," + grantedAuthority);
filter.getPropertyValues().addPropertyValue(ATT_KEY, key);
BeanDefinition authManager = ConfigUtils.registerProviderManagerIfNecessary(parserContext);
RootBeanDefinition provider = new RootBeanDefinition(AnonymousAuthenticationProvider.class);
provider.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
provider.setSource(source);
provider.getPropertyValues().addPropertyValue(ATT_KEY, key);
parserContext.getRegistry().registerBeanDefinition(BeanIds.ANONYMOUS_AUTHENTICATION_PROVIDER, provider);
ConfigUtils.addAuthenticationProvider(parserContext, BeanIds.ANONYMOUS_AUTHENTICATION_PROVIDER);
ManagedList authMgrProviderList = (ManagedList) authManager.getPropertyValues().getPropertyValue("providers").getValue();
authMgrProviderList.add(provider);
parserContext.getRegistry().registerBeanDefinition(BeanIds.ANONYMOUS_PROCESSING_FILTER, filter);
ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.ANONYMOUS_PROCESSING_FILTER));
@@ -22,7 +22,7 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
private static final String ATT_ALIAS = "alias";
public BeanDefinition parse(Element element, ParserContext parserContext) {
ConfigUtils.registerProviderManagerIfNecessary(parserContext);
BeanDefinition authManager = ConfigUtils.registerProviderManagerIfNecessary(parserContext);
String alias = element.getAttribute(ATT_ALIAS);
@@ -33,7 +33,6 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
String sessionControllerRef = element.getAttribute(ATT_SESSION_CONTROLLER_REF);
if (StringUtils.hasText(sessionControllerRef)) {
BeanDefinition authManager = parserContext.getRegistry().getBeanDefinition(BeanIds.AUTHENTICATION_MANAGER);
ConfigUtils.setSessionControllerOnAuthenticationManager(parserContext,
BeanIds.CONCURRENT_SESSION_CONTROLLER, element);
authManager.getPropertyValues().addPropertyValue("sessionController",
@@ -94,7 +94,7 @@ class AuthenticationProviderBeanDefinitionParser implements BeanDefinitionParser
parserContext.getRegistry().registerBeanDefinition(name , cacheResolver);
parserContext.registerComponent(new BeanComponentDefinition(cacheResolver, name));
ConfigUtils.addAuthenticationProvider(parserContext, id);
ConfigUtils.getRegisteredProviders(parserContext).add(new RuntimeBeanReference(id));
return null;
}
@@ -42,7 +42,6 @@ public abstract class BeanIds {
public static final String MAIN_ENTRY_POINT = "_mainEntryPoint";
public static final String FILTER_CHAIN_PROXY = "_filterChainProxy";
public static final String HTTP_SESSION_CONTEXT_INTEGRATION_FILTER = "_httpSessionContextIntegrationFilter";
public static final String LDAP_AUTHENTICATION_PROVIDER = "_ldapAuthenticationProvider";
public static final String LOGOUT_FILTER = "_logoutFilter";
public static final String EXCEPTION_TRANSLATION_FILTER = "_exceptionTranslationFilter";
public static final String FILTER_SECURITY_INTERCEPTOR = "_filterSecurityInterceptor";
@@ -50,7 +49,6 @@ public abstract class BeanIds {
public static final String CHANNEL_DECISION_MANAGER = "_channelDecisionManager";
public static final String REMEMBER_ME_FILTER = "_rememberMeFilter";
public static final String REMEMBER_ME_SERVICES = "_rememberMeServices";
public static final String REMEMBER_ME_AUTHENTICATION_PROVIDER = "_rememberMeAuthenticationProvider";
public static final String DEFAULT_LOGIN_PAGE_GENERATING_FILTER = "_defaultLoginPageFilter";
public static final String SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER = "_securityContextHolderAwareRequestFilter";
public static final String SESSION_FIXATION_PROTECTION_FILTER = "_sessionFixationProtectionFilter";
@@ -68,4 +66,5 @@ public abstract class BeanIds {
public static final String X509_AUTH_PROVIDER = "_x509AuthenticationProvider";
public static final String PRE_AUTH_ENTRY_POINT = "_preAuthenticatedProcessingFilterEntryPoint";
public static final String REMEMBER_ME_SERVICES_INJECTION_POST_PROCESSOR = "_rememberMeServicesInjectionBeanPostProcessor";
}
@@ -1,7 +1,7 @@
package org.springframework.security.config;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -9,12 +9,15 @@ import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.afterinvocation.AfterInvocationProviderManager;
import org.springframework.security.providers.ProviderManager;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.util.UrlUtils;
import org.springframework.security.vote.AffirmativeBased;
import org.springframework.security.vote.AuthenticatedVoter;
@@ -77,20 +80,21 @@ public abstract class ConfigUtils {
* using the &lt;security:provider /> tag or by other beans which have a dependency on the
* authentication manager.
*/
static void registerProviderManagerIfNecessary(ParserContext parserContext) {
static BeanDefinition registerProviderManagerIfNecessary(ParserContext parserContext) {
if(parserContext.getRegistry().containsBeanDefinition(BeanIds.AUTHENTICATION_MANAGER)) {
return;
return parserContext.getRegistry().getBeanDefinition(BeanIds.AUTHENTICATION_MANAGER);
}
BeanDefinition authManager = new RootBeanDefinition(NamespaceAuthenticationManager.class);
authManager.getPropertyValues().addPropertyValue("providerBeanNames", new ArrayList());
BeanDefinition authManager = new RootBeanDefinition(ProviderManager.class);
authManager.getPropertyValues().addPropertyValue("providers", new ManagedList());
parserContext.getRegistry().registerBeanDefinition(BeanIds.AUTHENTICATION_MANAGER, authManager);
return authManager;
}
static void addAuthenticationProvider(ParserContext parserContext, String beanName) {
registerProviderManagerIfNecessary(parserContext);
BeanDefinition authManager = parserContext.getRegistry().getBeanDefinition(BeanIds.AUTHENTICATION_MANAGER);
((ArrayList) authManager.getPropertyValues().getPropertyValue("providerBeanNames").getValue()).add(beanName);
static ManagedList getRegisteredProviders(ParserContext parserContext) {
BeanDefinition authManager = registerProviderManagerIfNecessary(parserContext);
return (ManagedList) authManager.getPropertyValues().getPropertyValue("providers").getValue();
}
static ManagedList getRegisteredAfterInvocationProviders(ParserContext parserContext) {
@@ -168,8 +172,7 @@ public abstract class ConfigUtils {
}
static void setSessionControllerOnAuthenticationManager(ParserContext pc, String beanName, Element sourceElt) {
registerProviderManagerIfNecessary(pc);
BeanDefinition authManager = pc.getRegistry().getBeanDefinition(BeanIds.AUTHENTICATION_MANAGER);
BeanDefinition authManager = registerProviderManagerIfNecessary(pc);
PropertyValue pv = authManager.getPropertyValues().getPropertyValue("sessionController");
if (pv != null && pv.getValue() != null) {
@@ -17,7 +17,7 @@ import org.w3c.dom.Node;
*/
public class CustomAuthenticationProviderBeanDefinitionDecorator implements BeanDefinitionDecorator {
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, ParserContext parserContext) {
ConfigUtils.addAuthenticationProvider(parserContext, holder.getBeanName());
ConfigUtils.getRegisteredProviders(parserContext).add(new RuntimeBeanReference(holder.getBeanName()));
return holder;
}
@@ -50,16 +50,16 @@ import org.w3c.dom.Element;
* @version $Id$
*/
public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
static final Log logger = LogFactory.getLog(HttpSecurityBeanDefinitionParser.class);
protected final Log logger = LogFactory.getLog(getClass());
static final String ATT_REALM = "realm";
static final String DEF_REALM = "Spring Security Application";
static final String ATT_PATH_PATTERN = "pattern";
static final String ATT_SESSION_FIXATION_PROTECTION = "session-fixation-protection";
static final String OPT_SESSION_FIXATION_NO_PROTECTION = "none";
static final String OPT_SESSION_FIXATION_CLEAN_SESSION = "newSession";
static final String OPT_SESSION_FIXATION_CLEAN_SESSION = "newSession";
static final String OPT_SESSION_FIXATION_MIGRATE_SESSION = "migrateSession";
static final String ATT_PATH_TYPE = "path-type";
@@ -91,9 +91,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
static final String ATT_SERVLET_API_PROVISION = "servlet-api-provision";
static final String DEF_SERVLET_API_PROVISION = "true";
static final String ATT_ACCESS_MGR = "access-decision-manager-ref";
static final String ATT_ACCESS_MGR = "access-decision-manager-ref";
static final String ATT_USER_SERVICE_REF = "user-service-ref";
static final String ATT_ENTRY_POINT_REF = "entry-point-ref";
static final String ATT_ONCE_PER_REQUEST = "once-per-request";
static final String ATT_ACCESS_DENIED_PAGE = "access-denied-page";
@@ -106,20 +106,20 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
// SEC-501 - should paths stored in request maps be converted to lower case
// true if Ant path and using lower case
final boolean convertPathsToLowerCase = (matcher instanceof AntUrlPathMatcher) && matcher.requiresLowerCaseUrl();
final List interceptUrlElts = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL);
final Map filterChainMap = new LinkedHashMap();
final LinkedHashMap channelRequestMap = new LinkedHashMap();
registerFilterChainProxy(parserContext, filterChainMap, matcher, source);
parseInterceptUrlsForChannelSecurityAndFilterChain(interceptUrlElts, filterChainMap, channelRequestMap,
parseInterceptUrlsForChannelSecurityAndFilterChain(interceptUrlElts, filterChainMap, channelRequestMap,
convertPathsToLowerCase, parserContext);
boolean allowSessionCreation = registerHttpSessionIntegrationFilter(element, parserContext);
registerServletApiFilter(element, parserContext);
// Set up the access manager reference for http
String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
@@ -127,7 +127,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
ConfigUtils.registerDefaultAccessManagerIfNecessary(parserContext);
accessManagerId = BeanIds.ACCESS_MANAGER;
}
// Register the portMapper. A default will always be created, even if no element exists.
BeanDefinition portMapper = new PortMappingsBeanDefinitionParser().parse(
DomUtils.getChildElementByTagName(element, Elements.PORT_MAPPINGS), parserContext);
@@ -139,19 +139,19 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
if (channelRequestMap.size() > 0) {
// At least one channel requirement has been specified
registerChannelProcessingBeans(parserContext, matcher, channelRequestMap);
}
registerFilterSecurityInterceptor(element, parserContext, matcher, accessManagerId,
}
registerFilterSecurityInterceptor(element, parserContext, matcher, accessManagerId,
parseInterceptUrlsForFilterInvocationRequestMap(interceptUrlElts, convertPathsToLowerCase, parserContext));
boolean sessionControlEnabled = registerConcurrentSessionControlBeansIfRequired(element, parserContext);
registerSessionFixationProtectionFilter(parserContext, element.getAttribute(ATT_SESSION_FIXATION_PROTECTION),
registerSessionFixationProtectionFilter(parserContext, element.getAttribute(ATT_SESSION_FIXATION_PROTECTION),
sessionControlEnabled);
boolean autoConfig = false;
if ("true".equals(element.getAttribute(ATT_AUTO_CONFIG))) {
autoConfig = true;
autoConfig = true;
}
Element anonymousElt = DomUtils.getChildElementByTagName(element, Elements.ANONYMOUS);
@@ -159,8 +159,21 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
new AnonymousBeanDefinitionParser().parse(anonymousElt, parserContext);
}
parseRememberMeAndLogout(element, autoConfig, parserContext);
// Parse remember me before logout as RememberMeServices is also a LogoutHandler implementation.
Element rememberMeElt = DomUtils.getChildElementByTagName(element, Elements.REMEMBER_ME);
if (rememberMeElt != null || autoConfig) {
new RememberMeBeanDefinitionParser().parse(rememberMeElt, parserContext);
// Post processor to inject RememberMeServices into filters which need it
RootBeanDefinition rememberMeInjectionPostProcessor = new RootBeanDefinition(RememberMeServicesInjectionBeanPostProcessor.class);
rememberMeInjectionPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES_INJECTION_POST_PROCESSOR, rememberMeInjectionPostProcessor);
}
Element logoutElt = DomUtils.getChildElementByTagName(element, Elements.LOGOUT);
if (logoutElt != null || autoConfig) {
new LogoutBeanDefinitionParser().parse(logoutElt, parserContext);
}
parseBasicFormLoginAndOpenID(element, parserContext, autoConfig, allowSessionCreation);
Element x509Elt = DomUtils.getChildElementByTagName(element, Elements.X509);
@@ -175,49 +188,27 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
RootBeanDefinition postProcessor2 = new RootBeanDefinition(UserDetailsServiceInjectionBeanPostProcessor.class);
postProcessor2.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(BeanIds.USER_DETAILS_SERVICE_INJECTION_POST_PROCESSOR, postProcessor2);
return null;
}
private void parseRememberMeAndLogout(Element elt, boolean autoConfig, ParserContext pc) {
// Parse remember me before logout as RememberMeServices is also a LogoutHandler implementation.
Element rememberMeElt = DomUtils.getChildElementByTagName(elt, Elements.REMEMBER_ME);
String rememberMeServices = null;
if (rememberMeElt != null || autoConfig) {
RememberMeBeanDefinitionParser rmbdp = new RememberMeBeanDefinitionParser();
rmbdp.parse(rememberMeElt, pc);
rememberMeServices = rmbdp.getServicesName();
// Post processor to inject RememberMeServices into filters which need it
RootBeanDefinition rememberMeInjectionPostProcessor = new RootBeanDefinition(RememberMeServicesInjectionBeanPostProcessor.class);
rememberMeInjectionPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES_INJECTION_POST_PROCESSOR, rememberMeInjectionPostProcessor);
}
Element logoutElt = DomUtils.getChildElementByTagName(elt, Elements.LOGOUT);
if (logoutElt != null || autoConfig) {
new LogoutBeanDefinitionParser(rememberMeServices).parse(logoutElt, pc);
}
}
private void registerFilterChainProxy(ParserContext pc, Map filterChainMap, UrlMatcher matcher, Object source) {
if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
pc.getReaderContext().error("Duplicate <http> element detected", source);
}
RootBeanDefinition filterChainProxy = new RootBeanDefinition(FilterChainProxy.class);
filterChainProxy.setSource(source);
filterChainProxy.getPropertyValues().addPropertyValue("matcher", matcher);
filterChainProxy.getPropertyValues().addPropertyValue("stripQueryStringFromUrls", Boolean.valueOf(matcher instanceof AntUrlPathMatcher));
filterChainProxy.getPropertyValues().addPropertyValue("filterChainMap", filterChainMap);
pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_CHAIN_PROXY, filterChainProxy);
pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);
pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);
}
private boolean registerHttpSessionIntegrationFilter(Element element, ParserContext pc) {
RootBeanDefinition httpScif = new RootBeanDefinition(HttpSessionContextIntegrationFilter.class);
boolean sessionCreationAllowed = true;
String createSession = element.getAttribute(ATT_CREATE_SESSION);
if (OPT_CREATE_SESSION_ALWAYS.equals(createSession)) {
httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.TRUE);
@@ -234,11 +225,11 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
pc.getRegistry().registerBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER, httpScif);
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER));
return sessionCreationAllowed;
}
// Adds the servlet-api integration filter if required
// Adds the servlet-api integration filter if required
private void registerServletApiFilter(Element element, ParserContext pc) {
String provideServletApi = element.getAttribute(ATT_SERVLET_API_PROVISION);
if (!StringUtils.hasText(provideServletApi)) {
@@ -251,27 +242,27 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER));
}
}
private boolean registerConcurrentSessionControlBeansIfRequired(Element element, ParserContext parserContext) {
Element sessionControlElt = DomUtils.getChildElementByTagName(element, Elements.CONCURRENT_SESSIONS);
if (sessionControlElt == null) {
return false;
}
new ConcurrentSessionsBeanDefinitionParser().parse(sessionControlElt, parserContext);
logger.info("Concurrent session filter in use, setting 'forceEagerSessionCreation' to true");
BeanDefinition sessionIntegrationFilter = parserContext.getRegistry().getBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER);
BeanDefinition sessionIntegrationFilter = parserContext.getRegistry().getBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER);
sessionIntegrationFilter.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
return true;
}
private void registerExceptionTranslationFilter(Element element, ParserContext pc, boolean allowSessionCreation) {
String accessDeniedPage = element.getAttribute(ATT_ACCESS_DENIED_PAGE);
ConfigUtils.validateHttpRedirect(accessDeniedPage, pc, pc.extractSource(element));
String accessDeniedPage = element.getAttribute(ATT_ACCESS_DENIED_PAGE);
ConfigUtils.validateHttpRedirect(accessDeniedPage, pc, pc.extractSource(element));
BeanDefinitionBuilder exceptionTranslationFilterBuilder
= BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class);
exceptionTranslationFilterBuilder.addPropertyValue("createSessionAllowed", new Boolean(allowSessionCreation));
if (StringUtils.hasText(accessDeniedPage)) {
AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl();
accessDeniedHandler.setErrorPage(accessDeniedPage);
@@ -281,27 +272,27 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
pc.getRegistry().registerBeanDefinition(BeanIds.EXCEPTION_TRANSLATION_FILTER, exceptionTranslationFilterBuilder.getBeanDefinition());
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.EXCEPTION_TRANSLATION_FILTER));
}
private void registerFilterSecurityInterceptor(Element element, ParserContext pc, UrlMatcher matcher,
String accessManagerId, LinkedHashMap filterInvocationDefinitionMap) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class);
builder.addPropertyReference("accessDecisionManager", accessManagerId);
builder.addPropertyReference("authenticationManager", BeanIds.AUTHENTICATION_MANAGER);
if ("false".equals(element.getAttribute(ATT_ONCE_PER_REQUEST))) {
builder.addPropertyValue("observeOncePerRequest", Boolean.FALSE);
}
DefaultFilterInvocationDefinitionSource fids =
DefaultFilterInvocationDefinitionSource fids =
new DefaultFilterInvocationDefinitionSource(matcher, filterInvocationDefinitionMap);
fids.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher);
builder.addPropertyValue("objectDefinitionSource", fids);
pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_SECURITY_INTERCEPTOR, builder.getBeanDefinition());
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FILTER_SECURITY_INTERCEPTOR));
}
private void registerChannelProcessingBeans(ParserContext pc, UrlMatcher matcher, LinkedHashMap channelRequestMap) {
RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class);
channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager",
@@ -309,7 +300,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
DefaultFilterInvocationDefinitionSource channelFilterInvDefSource =
new DefaultFilterInvocationDefinitionSource(matcher, channelRequestMap);
channelFilterInvDefSource.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher);
channelFilter.getPropertyValues().addPropertyValue("filterInvocationDefinitionSource",
channelFilterInvDefSource);
RootBeanDefinition channelDecisionManager = new RootBeanDefinition(ChannelDecisionManagerImpl.class);
@@ -330,161 +321,161 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_PROCESSING_FILTER, channelFilter);
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.CHANNEL_PROCESSING_FILTER));
pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_DECISION_MANAGER, channelDecisionManager);
}
private void registerSessionFixationProtectionFilter(ParserContext pc, String sessionFixationAttribute, boolean sessionControlEnabled) {
if(!StringUtils.hasText(sessionFixationAttribute)) {
sessionFixationAttribute = OPT_SESSION_FIXATION_MIGRATE_SESSION;
}
if (!sessionFixationAttribute.equals(OPT_SESSION_FIXATION_NO_PROTECTION)) {
BeanDefinitionBuilder sessionFixationFilter =
BeanDefinitionBuilder sessionFixationFilter =
BeanDefinitionBuilder.rootBeanDefinition(SessionFixationProtectionFilter.class);
sessionFixationFilter.addPropertyValue("migrateSessionAttributes",
sessionFixationFilter.addPropertyValue("migrateSessionAttributes",
Boolean.valueOf(sessionFixationAttribute.equals(OPT_SESSION_FIXATION_MIGRATE_SESSION)));
if (sessionControlEnabled) {
sessionFixationFilter.addPropertyReference("sessionRegistry", BeanIds.SESSION_REGISTRY);
}
pc.getRegistry().registerBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER,
pc.getRegistry().registerBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER,
sessionFixationFilter.getBeanDefinition());
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SESSION_FIXATION_PROTECTION_FILTER));
}
}
private void parseBasicFormLoginAndOpenID(Element element, ParserContext pc, boolean autoConfig, boolean allowSessionCreation) {
RootBeanDefinition formLoginFilter = null;
RootBeanDefinition formLoginEntryPoint = null;
String formLoginPage = null;
String formLoginPage = null;
RootBeanDefinition openIDFilter = null;
RootBeanDefinition openIDEntryPoint = null;
String openIDLoginPage = null;
String realm = element.getAttribute(ATT_REALM);
if (!StringUtils.hasText(realm)) {
realm = DEF_REALM;
realm = DEF_REALM;
}
Element basicAuthElt = DomUtils.getChildElementByTagName(element, Elements.BASIC_AUTH);
if (basicAuthElt != null || autoConfig) {
new BasicAuthenticationBeanDefinitionParser(realm).parse(basicAuthElt, pc);
}
Element formLoginElt = DomUtils.getChildElementByTagName(element, Elements.FORM_LOGIN);
Element formLoginElt = DomUtils.getChildElementByTagName(element, Elements.FORM_LOGIN);
if (formLoginElt != null || autoConfig) {
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_security_check",
"org.springframework.security.ui.webapp.AuthenticationProcessingFilter");
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_security_check",
"org.springframework.security.ui.webapp.AuthenticationProcessingFilter");
parser.parse(formLoginElt, pc);
formLoginFilter = parser.getFilterBean();
formLoginEntryPoint = parser.getEntryPointBean();
formLoginPage = parser.getLoginPage();
}
Element openIDLoginElt = DomUtils.getChildElementByTagName(element, Elements.OPENID_LOGIN);
if (openIDLoginElt != null) {
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_openid_security_check",
"org.springframework.security.ui.openid.OpenIDAuthenticationProcessingFilter");
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_openid_security_check",
"org.springframework.security.ui.openid.OpenIDAuthenticationProcessingFilter");
parser.parse(openIDLoginElt, pc);
openIDFilter = parser.getFilterBean();
openIDEntryPoint = parser.getEntryPointBean();
openIDLoginPage = parser.getLoginPage();
BeanDefinitionBuilder openIDProviderBuilder =
BeanDefinitionBuilder openIDProviderBuilder =
BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.providers.openid.OpenIDAuthenticationProvider");
String userService = openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF);
if (StringUtils.hasText(userService)) {
openIDProviderBuilder.addPropertyReference("userDetailsService", userService);
}
BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition();
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_PROVIDER, openIDProvider);
ConfigUtils.addAuthenticationProvider(pc, BeanIds.OPEN_ID_PROVIDER);
ConfigUtils.getRegisteredProviders(pc).add(new RuntimeBeanReference(BeanIds.OPEN_ID_PROVIDER));
}
boolean needLoginPage = false;
if (formLoginFilter != null) {
needLoginPage = true;
formLoginFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_FILTER, formLoginFilter);
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_ENTRY_POINT, formLoginEntryPoint);
}
needLoginPage = true;
formLoginFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_FILTER, formLoginFilter);
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_ENTRY_POINT, formLoginEntryPoint);
}
if (openIDFilter != null) {
needLoginPage = true;
openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_FILTER, openIDFilter);
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_ENTRY_POINT, openIDEntryPoint);
needLoginPage = true;
openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_FILTER, openIDFilter);
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_ENTRY_POINT, openIDEntryPoint);
}
// If no login page has been defined, add in the default page generator.
if (needLoginPage && formLoginPage == null && openIDLoginPage == null) {
logger.info("No login page configured. The default internal one will be used. Use the '"
+ FormLoginBeanDefinitionParser.ATT_LOGIN_PAGE + "' attribute to set the URL of the login page.");
BeanDefinitionBuilder loginPageFilter =
BeanDefinitionBuilder.rootBeanDefinition(DefaultLoginPageGeneratingFilter.class);
BeanDefinitionBuilder loginPageFilter =
BeanDefinitionBuilder.rootBeanDefinition(DefaultLoginPageGeneratingFilter.class);
if (formLoginFilter != null) {
loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
}
if (openIDFilter != null) {
loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
}
pc.getRegistry().registerBeanDefinition(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER,
loginPageFilter.getBeanDefinition());
pc.getRegistry().registerBeanDefinition(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER,
loginPageFilter.getBeanDefinition());
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER));
}
// We need to establish the main entry point.
// First check if a custom entry point bean is set
String customEntryPoint = element.getAttribute(ATT_ENTRY_POINT_REF);
if (StringUtils.hasText(customEntryPoint)) {
pc.getRegistry().registerAlias(customEntryPoint, BeanIds.MAIN_ENTRY_POINT);
return;
}
// Basic takes precedence if explicit element is used and no others are configured
if (basicAuthElt != null && formLoginElt == null && openIDLoginElt == null) {
pc.getRegistry().registerAlias(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
return;
pc.getRegistry().registerAlias(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
return;
}
// If formLogin has been enabled either through an element or auto-config, then it is used if no openID login page
// has been set
if (formLoginFilter != null && openIDLoginPage == null) {
pc.getRegistry().registerAlias(BeanIds.FORM_LOGIN_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
return;
pc.getRegistry().registerAlias(BeanIds.FORM_LOGIN_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
return;
}
// Otherwise use OpenID if enabled
if (openIDFilter != null && formLoginFilter == null) {
pc.getRegistry().registerAlias(BeanIds.OPEN_ID_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
return;
pc.getRegistry().registerAlias(BeanIds.OPEN_ID_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
return;
}
// If X.509 has been enabled, use the preauth entry point.
if (DomUtils.getChildElementByTagName(element, Elements.X509) != null) {
pc.getRegistry().registerAlias(BeanIds.PRE_AUTH_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
return;
}
pc.getReaderContext().error("No AuthenticationEntryPoint could be established. Please " +
"make sure you have a login mechanism configured through the namespace (such as form-login) or " +
"specify a custom AuthenticationEntryPoint with the custom-entry-point-ref attribute ",
"make sure you have a login mechanism configured through the namespace (such as form-login) or " +
"specify a custom AuthenticationEntryPoint with the custom-entry-point-ref attribute ",
pc.extractSource(element));
}
static UrlMatcher createUrlMatcher(Element element) {
String patternType = element.getAttribute(ATT_PATH_TYPE);
if (!StringUtils.hasText(patternType)) {
@@ -518,8 +509,8 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
}
// Default for regex is no change
}
return matcher;
return matcher;
}
/**
@@ -563,7 +554,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
editor.setAsText(channelConfigAttribute);
channelRequestMap.put(new RequestKey(path), (ConfigAttributeDefinition) editor.getValue());
}
String filters = urlElt.getAttribute(ATT_FILTERS);
if (StringUtils.hasText(filters)) {
@@ -576,10 +567,10 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
}
}
}
static LinkedHashMap parseInterceptUrlsForFilterInvocationRequestMap(List urlElts, boolean useLowerCasePaths, ParserContext parserContext) {
LinkedHashMap filterInvocationDefinitionMap = new LinkedHashMap();
Iterator urlEltsIterator = urlElts.iterator();
ConfigAttributeEditor editor = new ConfigAttributeEditor();
@@ -606,17 +597,11 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
// Convert the comma-separated list of access attributes to a ConfigAttributeDefinition
if (StringUtils.hasText(access)) {
editor.setAsText(access);
Object key = new RequestKey(path, method);
if (filterInvocationDefinitionMap.containsKey(key)) {
logger.warn("Duplicate URL defined: " + key + ". The original attribute values will be overwritten");
}
filterInvocationDefinitionMap.put(key, editor.getValue());
filterInvocationDefinitionMap.put(new RequestKey(path, method), editor.getValue());
}
}
return filterInvocationDefinitionMap;
}
}
@@ -50,7 +50,7 @@ public class JdbcUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
if (StringUtils.hasText(groupAuthoritiesQuery)) {
builder.addPropertyValue("enableGroups", Boolean.TRUE);
builder.addPropertyValue("groupAuthoritiesByUsernameQuery", groupAuthoritiesQuery);
builder.addPropertyValue("authoritiesByUsernameQuery", groupAuthoritiesQuery);
}
}
}
@@ -100,9 +100,8 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser {
ldapProvider.addConstructorArg(LdapUserServiceBeanDefinitionParser.parseAuthoritiesPopulator(elt, parserContext));
ldapProvider.addPropertyValue("userDetailsContextMapper",
LdapUserServiceBeanDefinitionParser.parseUserDetailsClass(elt, parserContext));
parserContext.getRegistry().registerBeanDefinition(BeanIds.LDAP_AUTHENTICATION_PROVIDER, ldapProvider.getBeanDefinition());
ConfigUtils.addAuthenticationProvider(parserContext, BeanIds.LDAP_AUTHENTICATION_PROVIDER);
ConfigUtils.getRegisteredProviders(parserContext).add(ldapProvider.getBeanDefinition());
return null;
}
@@ -14,22 +14,22 @@ import org.w3c.dom.Element;
* @since 2.0
*/
public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServiceBeanDefinitionParser {
public static final String ATT_SERVER = "server-ref";
public static final String ATT_SERVER = "server-ref";
public static final String ATT_USER_SEARCH_FILTER = "user-search-filter";
public static final String ATT_USER_SEARCH_BASE = "user-search-base";
public static final String DEF_USER_SEARCH_BASE = "";
public static final String ATT_GROUP_SEARCH_FILTER = "group-search-filter";
public static final String ATT_GROUP_SEARCH_BASE = "group-search-base";
public static final String ATT_GROUP_ROLE_ATTRIBUTE = "group-role-attribute";
public static final String ATT_GROUP_ROLE_ATTRIBUTE = "group-role-attribute";
public static final String DEF_GROUP_SEARCH_FILTER = "(uniqueMember={0})";
public static final String DEF_GROUP_SEARCH_BASE = "";
public static final String DEF_GROUP_SEARCH_BASE = "ou=groups";
static final String ATT_ROLE_PREFIX = "role-prefix";
static final String ATT_USER_CLASS = "user-details-class";
static final String OPT_PERSON = "person";
static final String OPT_INETORGPERSON = "inetOrgPerson";
public static final String LDAP_SEARCH_CLASS = "org.springframework.security.ldap.search.FilterBasedLdapUserSearch";
public static final String PERSON_MAPPER_CLASS = "org.springframework.security.userdetails.ldap.PersonContextMapper";
public static final String INET_ORG_PERSON_MAPPER_CLASS = "org.springframework.security.userdetails.ldap.InetOrgPersonContextMapper";
@@ -45,42 +45,42 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
if (!StringUtils.hasText(elt.getAttribute(ATT_USER_SEARCH_FILTER))) {
parserContext.getReaderContext().error("User search filter must be supplied", elt);
}
builder.addConstructorArg(parseSearchBean(elt, parserContext));
builder.addConstructorArg(parseAuthoritiesPopulator(elt, parserContext));
builder.addPropertyValue("userDetailsMapper", parseUserDetailsClass(elt, parserContext));
}
static RootBeanDefinition parseSearchBean(Element elt, ParserContext parserContext) {
String userSearchFilter = elt.getAttribute(ATT_USER_SEARCH_FILTER);
String userSearchBase = elt.getAttribute(ATT_USER_SEARCH_BASE);
Object source = parserContext.extractSource(elt);
if (StringUtils.hasText(userSearchBase)) {
if(!StringUtils.hasText(userSearchFilter)) {
parserContext.getReaderContext().error(ATT_USER_SEARCH_BASE + " cannot be used without a " + ATT_USER_SEARCH_FILTER, source);
}
} else {
userSearchBase = DEF_USER_SEARCH_BASE;
}
}
if (!StringUtils.hasText(userSearchFilter)) {
return null;
}
BeanDefinitionBuilder searchBuilder = BeanDefinitionBuilder.rootBeanDefinition(LDAP_SEARCH_CLASS);
searchBuilder.setSource(source);
searchBuilder.addConstructorArg(userSearchBase);
searchBuilder.addConstructorArg(userSearchFilter);
searchBuilder.addConstructorArg(parseServerReference(elt, parserContext));
return (RootBeanDefinition) searchBuilder.getBeanDefinition();
}
static RuntimeBeanReference parseServerReference(Element elt, ParserContext parserContext) {
String server = elt.getAttribute(ATT_SERVER);
boolean requiresDefaultName = false;
if (!StringUtils.hasText(server)) {
server = BeanIds.CONTEXT_SOURCE;
requiresDefaultName = true;
@@ -89,27 +89,27 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
RuntimeBeanReference contextSource = new RuntimeBeanReference(server);
contextSource.setSource(parserContext.extractSource(elt));
LdapConfigUtils.registerPostProcessorIfNecessary(parserContext.getRegistry(), requiresDefaultName);
return contextSource;
}
static RootBeanDefinition parseUserDetailsClass(Element elt, ParserContext parserContext) {
String userDetailsClass = elt.getAttribute(ATT_USER_CLASS);
if (OPT_PERSON.equals(userDetailsClass)) {
return new RootBeanDefinition(PERSON_MAPPER_CLASS, null, null);
} else if (OPT_INETORGPERSON.equals(userDetailsClass)) {
return new RootBeanDefinition(INET_ORG_PERSON_MAPPER_CLASS, null, null);
}
return new RootBeanDefinition(LDAP_USER_MAPPER_CLASS, null, null);
String userDetailsClass = elt.getAttribute(ATT_USER_CLASS);
if (OPT_PERSON.equals(userDetailsClass)) {
return new RootBeanDefinition(PERSON_MAPPER_CLASS, null, null);
} else if (OPT_INETORGPERSON.equals(userDetailsClass)) {
return new RootBeanDefinition(INET_ORG_PERSON_MAPPER_CLASS, null, null);
}
return new RootBeanDefinition(LDAP_USER_MAPPER_CLASS, null, null);
}
static RootBeanDefinition parseAuthoritiesPopulator(Element elt, ParserContext parserContext) {
String groupSearchFilter = elt.getAttribute(ATT_GROUP_SEARCH_FILTER);
String groupSearchBase = elt.getAttribute(ATT_GROUP_SEARCH_BASE);
String groupRoleAttribute = elt.getAttribute(ATT_GROUP_ROLE_ATTRIBUTE);
String rolePrefix = elt.getAttribute(ATT_ROLE_PREFIX);
if (!StringUtils.hasText(groupSearchFilter)) {
groupSearchFilter = DEF_GROUP_SEARCH_FILTER;
}
@@ -117,25 +117,25 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
if (!StringUtils.hasText(groupSearchBase)) {
groupSearchBase = DEF_GROUP_SEARCH_BASE;
}
BeanDefinitionBuilder populator = BeanDefinitionBuilder.rootBeanDefinition(LDAP_AUTHORITIES_POPULATOR_CLASS);
populator.setSource(parserContext.extractSource(elt));
populator.addConstructorArg(parseServerReference(elt, parserContext));
populator.addConstructorArg(groupSearchBase);
populator.addPropertyValue("groupSearchFilter", groupSearchFilter);
populator.addPropertyValue("searchSubtree", Boolean.TRUE);
if (StringUtils.hasText(rolePrefix)) {
if ("none".equals(rolePrefix)) {
rolePrefix = "";
}
populator.addPropertyValue("rolePrefix", rolePrefix);
}
if (StringUtils.hasLength(groupRoleAttribute)) {
populator.addPropertyValue("groupRoleAttribute", groupRoleAttribute);
}
return (RootBeanDefinition) populator.getBeanDefinition();
}
}
@@ -25,12 +25,6 @@ public class LogoutBeanDefinitionParser implements BeanDefinitionParser {
static final String ATT_LOGOUT_URL = "logout-url";
static final String DEF_LOGOUT_URL = "/j_spring_security_logout";
String rememberMeServices;
public LogoutBeanDefinitionParser(String rememberMeServices) {
this.rememberMeServices = rememberMeServices;
}
public BeanDefinition parse(Element element, ParserContext parserContext) {
String logoutUrl = null;
@@ -72,8 +66,8 @@ public class LogoutBeanDefinitionParser implements BeanDefinitionParser {
}
handlers.add(sclh);
if (rememberMeServices != null) {
handlers.add(new RuntimeBeanReference(rememberMeServices));
if (parserContext.getRegistry().containsBeanDefinition(BeanIds.REMEMBER_ME_SERVICES)) {
handlers.add(new RuntimeBeanReference(BeanIds.REMEMBER_ME_SERVICES));
}
builder.addConstructorArg(handlers);
@@ -1,59 +0,0 @@
package org.springframework.security.config;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.security.providers.ProviderManager;
import org.springframework.util.Assert;
/**
* Extended version of {@link ProviderManager the default authentication manager} which lazily initializes
* the list of {@link AuthenticationProvider}s. This prevents some of the issues that have occurred with
* namespace configuration where early instantiation of a security interceptor has caused the AuthenticationManager
* and thus dependent beans (typically UserDetailsService implementations or DAOs) to be initialized too early.
*
* @author Luke Taylor
* @since 2.0.4
*/
public class NamespaceAuthenticationManager extends ProviderManager implements BeanFactoryAware {
BeanFactory beanFactory;
List providerBeanNames;
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(providerBeanNames, "provideBeanNames has not been set");
Assert.notEmpty(providerBeanNames, "No authentication providers were found in the application context");
super.afterPropertiesSet();
}
/**
* Overridden to lazily-initialize the list of providers on first use.
*/
public List getProviders() {
// We use the names array to determine whether the list has been set yet.
if (providerBeanNames != null) {
List providers = new ArrayList();
Iterator beanNames = providerBeanNames.iterator();
while (beanNames.hasNext()) {
providers.add(beanFactory.getBean((String) beanNames.next()));
}
providerBeanNames = null;
setProviders(providers);
}
return super.getProviders();
}
public void setProviderBeanNames(List provideBeanNames) {
this.providerBeanNames = provideBeanNames;
}
}
@@ -22,7 +22,7 @@ import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* Adds the decorated "Filter" bean into the standard filter chain maintained by the FilterChainProxy.
* Adds the decorated "Filter" bean into the standard filter chain maintained by the FilterChainProxy.
* This allows user to add their own custom filters to the security chain. If the user's filter
* already implements Ordered, and no "order" attribute is specified, the filter's default order will be used.
*
@@ -33,7 +33,7 @@ public class OrderedFilterBeanDefinitionDecorator implements BeanDefinitionDecor
public static final String ATT_AFTER = "after";
public static final String ATT_BEFORE = "before";
public static final String ATT_POSITION = "position";
public static final String ATT_POSITION = "position";
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, ParserContext parserContext) {
Element elt = (Element)node;
@@ -48,7 +48,7 @@ public class OrderedFilterBeanDefinitionDecorator implements BeanDefinitionDecor
}
ConfigUtils.addHttpFilter(parserContext, wrapper.getBeanDefinition());
return holder;
}
@@ -59,26 +59,22 @@ public class OrderedFilterBeanDefinitionDecorator implements BeanDefinitionDecor
String after = elt.getAttribute(ATT_AFTER);
String before = elt.getAttribute(ATT_BEFORE);
String position = elt.getAttribute(ATT_POSITION);
if(ConfigUtils.countNonEmpty(new String[] {after, before, position}) != 1) {
pc.getReaderContext().error("A single '" + ATT_AFTER + "', '" + ATT_BEFORE + "', or '" +
ATT_POSITION + "' attribute must be supplied", pc.extractSource(elt));
pc.getReaderContext().error("A single '" + ATT_AFTER + "', '" + ATT_BEFORE + "', or '" +
ATT_POSITION + "' attribute must be supplied", pc.extractSource(elt));
}
if (StringUtils.hasText(position)) {
return Integer.toString(FilterChainOrder.getOrder(position));
return Integer.toString(FilterChainOrder.getOrder(position));
}
if (StringUtils.hasText(after)) {
int order = FilterChainOrder.getOrder(after);
return Integer.toString(order == Integer.MAX_VALUE ? order : order + 1);
return Integer.toString(FilterChainOrder.getOrder(after) + 1);
}
if (StringUtils.hasText(before)) {
int order = FilterChainOrder.getOrder(before);
return Integer.toString(order == Integer.MIN_VALUE ? order : order - 1);
return Integer.toString(FilterChainOrder.getOrder(before) - 1);
}
return null;
@@ -125,12 +121,12 @@ public class OrderedFilterBeanDefinitionDecorator implements BeanDefinitionDecor
return beanName;
}
public String toString() {
return "OrderedFilterDecorator[ delegate=" + delegate + "; order=" + getOrder() + "]";
}
Filter getDelegate() {
return delegate;
}
public String toString() {
return "OrderedFilterDecorator[ delegate=" + delegate + "; order=" + getOrder() + "]";
}
Filter getDelegate() {
return delegate;
}
}
}
@@ -32,7 +32,6 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
static final String ATT_TOKEN_VALIDITY = "token-validity-seconds";
protected final Log logger = LogFactory.getLog(getClass());
private String servicesName;
public BeanDefinition parse(Element element, ParserContext parserContext) {
String tokenRepository = null;
@@ -103,10 +102,8 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
}
services.setSource(source);
services.getPropertyValues().addPropertyValue(ATT_KEY, key);
parserContext.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES, services);
servicesName = BeanIds.REMEMBER_ME_SERVICES;
parserContext.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES, services);
} else {
servicesName = rememberMeServicesRef;
parserContext.getRegistry().registerAlias(rememberMeServicesRef, BeanIds.REMEMBER_ME_SERVICES);
}
@@ -117,17 +114,13 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
return null;
}
String getServicesName() {
return servicesName;
}
private void registerProvider(ParserContext pc, Object source, String key) {
//BeanDefinition authManager = ConfigUtils.registerProviderManagerIfNecessary(pc);
private void registerProvider(ParserContext pc, Object source, String key) {
BeanDefinition authManager = ConfigUtils.registerProviderManagerIfNecessary(pc);
RootBeanDefinition provider = new RootBeanDefinition(RememberMeAuthenticationProvider.class);
provider.setSource(source);
provider.getPropertyValues().addPropertyValue(ATT_KEY, key);
pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_AUTHENTICATION_PROVIDER, provider);
ConfigUtils.addAuthenticationProvider(pc, BeanIds.REMEMBER_ME_AUTHENTICATION_PROVIDER);
ManagedList providers = (ManagedList) authManager.getPropertyValues().getPropertyValue("providers").getValue();
providers.add(provider);
}
private void registerFilter(ParserContext pc, Object source) {
@@ -51,8 +51,7 @@ public class RememberMeServicesInjectionBeanPostProcessor implements BeanPostPro
Map beans = beanFactory.getBeansOfType(RememberMeServices.class);
Assert.isTrue(beans.size() > 0, "No RememberMeServices configured");
Assert.isTrue(beans.size() == 1, "Use of '<remember-me />' requires a single instance of RememberMeServices " +
"in the application context, but more than one was found.");
Assert.isTrue(beans.size() == 1, "More than one RememberMeServices bean found.");
return (RememberMeServices) beans.values().toArray()[0];
}
@@ -2,6 +2,8 @@ package org.springframework.security.config;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValue;
@@ -19,91 +21,91 @@ import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.util.Assert;
/**
* Registered by {@link HttpSecurityBeanDefinitionParser} to inject a UserDetailsService into
* the X509Provider, RememberMeServices and OpenIDAuthenticationProvider instances created by
* the namespace.
*
*
* @author Luke Taylor
* @since 2.0.2
*/
public class UserDetailsServiceInjectionBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
private ConfigurableListableBeanFactory beanFactory;
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (BeanIds.X509_AUTH_PROVIDER.equals(beanName)) {
injectUserDetailsServiceIntoX509Provider((PreAuthenticatedAuthenticationProvider) bean);
} else if (BeanIds.REMEMBER_ME_SERVICES.equals(beanName)) {
injectUserDetailsServiceIntoRememberMeServices((AbstractRememberMeServices)bean);
} else if (BeanIds.OPEN_ID_PROVIDER.equals(beanName)) {
injectUserDetailsServiceIntoOpenIDProvider(bean);
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
private final Log logger = LogFactory.getLog(getClass());
private ConfigurableListableBeanFactory beanFactory;
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (BeanIds.X509_AUTH_PROVIDER.equals(beanName)) {
injectUserDetailsServiceIntoX509Provider((PreAuthenticatedAuthenticationProvider) bean);
} else if (BeanIds.REMEMBER_ME_SERVICES.equals(beanName)) {
injectUserDetailsServiceIntoRememberMeServices((AbstractRememberMeServices)bean);
} else if (BeanIds.OPEN_ID_PROVIDER.equals(beanName)) {
injectUserDetailsServiceIntoOpenIDProvider(bean);
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
private void injectUserDetailsServiceIntoRememberMeServices(AbstractRememberMeServices services) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(BeanIds.REMEMBER_ME_SERVICES);
PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("userDetailsService");
if (pv == null) {
services.setUserDetailsService(getUserDetailsService());
services.setUserDetailsService(getUserDetailsService());
} else {
UserDetailsService cachingUserService = getCachingUserService(pv.getValue());
if (cachingUserService != null) {
services.setUserDetailsService(cachingUserService);
}
UserDetailsService cachingUserService = getCachingUserService(pv.getValue());
if (cachingUserService != null) {
services.setUserDetailsService(cachingUserService);
}
}
}
private void injectUserDetailsServiceIntoX509Provider(PreAuthenticatedAuthenticationProvider provider) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(BeanIds.X509_AUTH_PROVIDER);
PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("preAuthenticatedUserDetailsService");
UserDetailsByNameServiceWrapper wrapper = new UserDetailsByNameServiceWrapper();
if (pv == null) {
wrapper.setUserDetailsService(getUserDetailsService());
provider.setPreAuthenticatedUserDetailsService(wrapper);
wrapper.setUserDetailsService(getUserDetailsService());
provider.setPreAuthenticatedUserDetailsService(wrapper);
} else {
RootBeanDefinition preAuthUserService = (RootBeanDefinition) pv.getValue();
Object userService =
preAuthUserService.getPropertyValues().getPropertyValue("userDetailsService").getValue();
UserDetailsService cachingUserService = getCachingUserService(userService);
if (cachingUserService != null) {
wrapper.setUserDetailsService(cachingUserService);
provider.setPreAuthenticatedUserDetailsService(wrapper);
}
RootBeanDefinition preAuthUserService = (RootBeanDefinition) pv.getValue();
Object userService =
preAuthUserService.getPropertyValues().getPropertyValue("userDetailsService").getValue();
UserDetailsService cachingUserService = getCachingUserService(userService);
if (cachingUserService != null) {
wrapper.setUserDetailsService(cachingUserService);
provider.setPreAuthenticatedUserDetailsService(wrapper);
}
}
}
private void injectUserDetailsServiceIntoOpenIDProvider(Object bean) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(BeanIds.OPEN_ID_PROVIDER);
PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("userDetailsService");
if (pv == null) {
BeanWrapperImpl beanWrapper = new BeanWrapperImpl(bean);
BeanWrapperImpl beanWrapper = new BeanWrapperImpl(bean);
beanWrapper.setPropertyValue("userDetailsService", getUserDetailsService());
}
}
/**
* Obtains a user details service for use in RememberMeServices etc. Will return a caching version
* if available so should not be used for beans which need to separate the two.
* if available so should not be used for beans which need to separate the two.
*/
UserDetailsService getUserDetailsService() {
Map beans = beanFactory.getBeansOfType(CachingUserDetailsService.class);
if (beans.size() == 0) {
beans = beanFactory.getBeansOfType(UserDetailsService.class);
}
Map beans = beanFactory.getBeansOfType(CachingUserDetailsService.class);
if (beans.size() == 0) {
beans = beanFactory.getBeansOfType(UserDetailsService.class);
}
if (beans.size() == 0) {
throw new SecurityConfigurationException("No UserDetailsService registered.");
@@ -114,24 +116,24 @@ public class UserDetailsServiceInjectionBeanPostProcessor implements BeanPostPro
return (UserDetailsService) beans.values().toArray()[0];
}
private UserDetailsService getCachingUserService(Object userServiceRef) {
Assert.isInstanceOf(RuntimeBeanReference.class, userServiceRef,
"userDetailsService property value must be a RuntimeBeanReference");
String id = ((RuntimeBeanReference)userServiceRef).getBeanName();
// Overwrite with the caching version if available
String cachingId = id + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX;
if (beanFactory.containsBeanDefinition(cachingId)) {
return (UserDetailsService) beanFactory.getBean(cachingId);
}
return null;
Assert.isInstanceOf(RuntimeBeanReference.class, userServiceRef,
"userDetailsService property value must be a RuntimeBeanReference");
String id = ((RuntimeBeanReference)userServiceRef).getBeanName();
// Overwrite with the caching version if available
String cachingId = id + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX;
if (beanFactory.containsBeanDefinition(cachingId)) {
return (UserDetailsService) beanFactory.getBean(cachingId);
}
return null;
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
}
}
@@ -46,7 +46,7 @@ public class X509BeanDefinitionParser implements BeanDefinitionParser {
BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class);
parserContext.getRegistry().registerBeanDefinition(BeanIds.X509_AUTH_PROVIDER, provider);
ConfigUtils.addAuthenticationProvider(parserContext, BeanIds.X509_AUTH_PROVIDER);
ConfigUtils.getRegisteredProviders(parserContext).add(new RuntimeBeanReference(BeanIds.X509_AUTH_PROVIDER));
String userServiceRef = element.getAttribute(ATT_USER_SERVICE_REF);
@@ -18,11 +18,11 @@ import org.springframework.util.ObjectUtils;
* Abstract implementation of {@link MethodDefinitionSource} that supports both Spring AOP and AspectJ and
* caches configuration attribute resolution from: 1. specific target method; 2. target class; 3. declaring method;
* 4. declaring class/interface.
*
*
* <p>
* This class mimics the behaviour of Spring's AbstractFallbackTransactionAttributeSource class.
* </p>
*
*
* <p>
* Note that this class cannot extract security metadata where that metadata is expressed by way of
* a target method/class (ie #1 and #2 above) AND the target method/class is encapsulated in another
@@ -31,7 +31,7 @@ import org.springframework.util.ObjectUtils;
* another proxy), move the metadata to declared methods or interfaces the proxy implements, or provide
* your own replacement <tt>MethodDefinitionSource</tt>.
* </p>
*
*
* @author Ben Alex
* @version $Id$
* @since 2.0
@@ -39,16 +39,15 @@ import org.springframework.util.ObjectUtils;
public abstract class AbstractFallbackMethodDefinitionSource implements MethodDefinitionSource {
private static final Log logger = LogFactory.getLog(AbstractFallbackMethodDefinitionSource.class);
private final static Object NULL_CONFIG_ATTRIBUTE = new Object();
private final static Object NULL_CONFIG_ATTRIBUTE = new Object();
private final Map attributeCache = new HashMap();
public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException {
Assert.notNull(object, "Object cannot be null");
if (object instanceof MethodInvocation) {
MethodInvocation mi = (MethodInvocation) object;
Object target = mi.getThis();
return getAttributes(mi.getMethod(), target == null ? null : target.getClass());
MethodInvocation mi = (MethodInvocation) object;
return getAttributes(mi.getMethod(), mi.getThis().getClass());
}
if (object instanceof JoinPoint) {
@@ -60,143 +59,143 @@ public abstract class AbstractFallbackMethodDefinitionSource implements MethodDe
Method method = ClassUtils.getMethodIfAvailable(declaringType, targetMethodName, types);
Assert.notNull(method, "Could not obtain target method from JoinPoint: '"+ jp + "'");
return getAttributes(method, targetClass);
}
throw new IllegalArgumentException("Object must be a MethodInvocation or JoinPoint");
}
public final boolean supports(Class clazz) {
return (MethodInvocation.class.isAssignableFrom(clazz) || JoinPoint.class.isAssignableFrom(clazz));
}
public ConfigAttributeDefinition getAttributes(Method method, Class targetClass) {
// First, see if we have a cached value.
Object cacheKey = new DefaultCacheKey(method, targetClass);
synchronized (this.attributeCache) {
Object cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// Value will either be canonical value indicating there is no config attribute,
// or an actual config attribute.
if (cached == NULL_CONFIG_ATTRIBUTE) {
return null;
}
else {
return (ConfigAttributeDefinition) cached;
}
}
else {
// We need to work it out.
ConfigAttributeDefinition cfgAtt = computeAttributes(method, targetClass);
// Put it in the cache.
if (cfgAtt == null) {
this.attributeCache.put(cacheKey, NULL_CONFIG_ATTRIBUTE);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Adding security method [" + cacheKey + "] with attribute [" + cfgAtt + "]");
}
this.attributeCache.put(cacheKey, cfgAtt);
}
return cfgAtt;
}
}
// First, see if we have a cached value.
Object cacheKey = new DefaultCacheKey(method, targetClass);
synchronized (this.attributeCache) {
Object cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// Value will either be canonical value indicating there is no config attribute,
// or an actual config attribute.
if (cached == NULL_CONFIG_ATTRIBUTE) {
return null;
}
else {
return (ConfigAttributeDefinition) cached;
}
}
else {
// We need to work it out.
ConfigAttributeDefinition cfgAtt = computeAttributes(method, targetClass);
// Put it in the cache.
if (cfgAtt == null) {
this.attributeCache.put(cacheKey, NULL_CONFIG_ATTRIBUTE);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Adding security method [" + cacheKey + "] with attribute [" + cfgAtt + "]");
}
this.attributeCache.put(cacheKey, cfgAtt);
}
return cfgAtt;
}
}
}
/**
*
* @param method the method for the current invocation (never <code>null</code>)
* @param targetClass the target class for this invocation (may be <code>null</code>)
*
* @param method the method for the current invocation (never <code>null</code>)
* @param targetClass the target class for this invocation (may be <code>null</code>)
* @return
*/
private ConfigAttributeDefinition computeAttributes(Method method, Class targetClass) {
// The method may be on an interface, but we need attributes from the target class.
// If the target class is null, the method will be unchanged.
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
// First try is the method in the target class.
ConfigAttributeDefinition attr = findAttributes(specificMethod, targetClass);
if (attr != null) {
return attr;
}
// The method may be on an interface, but we need attributes from the target class.
// If the target class is null, the method will be unchanged.
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
// First try is the method in the target class.
ConfigAttributeDefinition attr = findAttributes(specificMethod, targetClass);
if (attr != null) {
return attr;
}
// Second try is the config attribute on the target class.
attr = findAttributes(specificMethod.getDeclaringClass());
if (attr != null) {
return attr;
}
// Second try is the config attribute on the target class.
attr = findAttributes(specificMethod.getDeclaringClass());
if (attr != null) {
return attr;
}
if (specificMethod != method || targetClass == null) {
// Fallback is to look at the original method.
attr = findAttributes(method, method.getDeclaringClass());
if (attr != null) {
return attr;
}
// Last fallback is the class of the original method.
return findAttributes(method.getDeclaringClass());
}
return null;
if (specificMethod != method) {
// Fallback is to look at the original method.
attr = findAttributes(method, method.getDeclaringClass());
if (attr != null) {
return attr;
}
// Last fallback is the class of the original method.
return findAttributes(method.getDeclaringClass());
}
return null;
}
/**
* Obtains the security metadata applicable to the specified method invocation.
*
*
* <p>
* Note that the {@link Method#getDeclaringClass()} may not equal the <code>targetClass</code>.
* Both parameters are provided to assist subclasses which may wish to provide advanced
* capabilities related to method metadata being "registered" against a method even if the
* target class does not declare the method (i.e. the subclass may only inherit the method).
*
*
* @param method the method for the current invocation (never <code>null</code>)
* @param targetClass the target class for the invocation (may be <code>null</code>)
* @return the security metadata (or null if no metadata applies)
*/
protected abstract ConfigAttributeDefinition findAttributes(Method method, Class targetClass);
/**
* Obtains the security metadata registered against the specified class.
*
*
* <p>
* Subclasses should only return metadata expressed at a class level. Subclasses should NOT
* aggregate metadata for each method registered against a class, as the abstract superclass
* will separate invoke {@link #findAttributes(Method, Class)} for individual methods as
* appropriate.
*
* appropriate.
*
* @param clazz the target class for the invocation (never <code>null</code>)
* @return the security metadata (or null if no metadata applies)
*/
protected abstract ConfigAttributeDefinition findAttributes(Class clazz);
private static class DefaultCacheKey {
private static class DefaultCacheKey {
private final Method method;
private final Class targetClass;
private final Method method;
private final Class targetClass;
public DefaultCacheKey(Method method, Class targetClass) {
this.method = method;
this.targetClass = targetClass;
}
public DefaultCacheKey(Method method, Class targetClass) {
this.method = method;
this.targetClass = targetClass;
}
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof DefaultCacheKey)) {
return false;
}
DefaultCacheKey otherKey = (DefaultCacheKey) other;
return (this.method.equals(otherKey.method) &&
ObjectUtils.nullSafeEquals(this.targetClass, otherKey.targetClass));
}
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof DefaultCacheKey)) {
return false;
}
DefaultCacheKey otherKey = (DefaultCacheKey) other;
return (this.method.equals(otherKey.method) &&
ObjectUtils.nullSafeEquals(this.targetClass, otherKey.targetClass));
}
public int hashCode() {
return this.method.hashCode() * 21 + (this.targetClass != null ? this.targetClass.hashCode() : 0);
}
public String toString() {
return "CacheKey[" + (targetClass == null ? "-" : targetClass.getName()) + "; " + method + "]";
}
}
public int hashCode() {
return this.method.hashCode() * 21 + (this.targetClass != null ? this.targetClass.hashCode() : 0);
}
public String toString() {
return "CacheKey[" + (targetClass == null ? "-" : targetClass.getName()) + "; " + method + "]";
}
}
}
@@ -34,13 +34,13 @@ import org.springframework.util.ClassUtils;
/**
* Stores a {@link ConfigAttributeDefinition} for a method or class signature.
*
*
* <p>
* This class is the preferred implementation of {@link MethodDefinitionSource} for XML-based
* definition of method security metadata. To assist in XML-based definition, wildcard support
* is provided.
* </p>
*
*
* @author Ben Alex
* @version $Id$
* @since 2.0
@@ -51,9 +51,9 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
private static final Log logger = LogFactory.getLog(MapBasedMethodDefinitionSource.class);
//~ Instance fields ================================================================================================
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
/** Map from RegisteredMethod to ConfigAttributeDefinition */
/** Map from RegisteredMethod to ConfigAttributeDefinition */
protected Map methodMap = new HashMap();
/** Map from RegisteredMethod to name pattern used for registration */
@@ -74,37 +74,48 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
addSecureMethod((String)entry.getKey(), (ConfigAttributeDefinition)entry.getValue());
}
}
}
/**
* Implementation does not support class-level attributes.
*/
protected ConfigAttributeDefinition findAttributes(Class clazz) {
return null;
}
/**
* Will walk the method inheritance tree to find the most specific declaration applicable.
*/
protected ConfigAttributeDefinition findAttributes(Method method, Class targetClass) {
return findAttributesSpecifiedAgainst(method, targetClass);
}
private ConfigAttributeDefinition findAttributesSpecifiedAgainst(Method method, Class clazz) {
RegisteredMethod registeredMethod = new RegisteredMethod(method, clazz);
if (methodMap.containsKey(registeredMethod)) {
return (ConfigAttributeDefinition) methodMap.get(registeredMethod);
}
// Search superclass
if (clazz.getSuperclass() != null) {
return findAttributesSpecifiedAgainst(method, clazz.getSuperclass());
}
return null;
}
/**
* Implementation does not support class-level attributes.
* Add configuration attributes for a secure method.
*
* @param method the method to be secured
* @param attr required authorities associated with the method
*/
protected ConfigAttributeDefinition findAttributes(Class clazz) {
return null;
}
/**
* Will walk the method inheritance tree to find the most specific declaration applicable.
*/
protected ConfigAttributeDefinition findAttributes(Method method, Class targetClass) {
if (targetClass == null) {
return null;
}
return findAttributesSpecifiedAgainst(method, targetClass);
}
private ConfigAttributeDefinition findAttributesSpecifiedAgainst(Method method, Class clazz) {
RegisteredMethod registeredMethod = new RegisteredMethod(method, clazz);
if (methodMap.containsKey(registeredMethod)) {
return (ConfigAttributeDefinition) methodMap.get(registeredMethod);
}
// Search superclass
if (clazz.getSuperclass() != null) {
return findAttributesSpecifiedAgainst(method, clazz.getSuperclass());
}
return null;
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);
}
/**
@@ -115,7 +126,7 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
* @param attr required authorities associated with the method
*/
public void addSecureMethod(String name, ConfigAttributeDefinition attr) {
int lastDotIndex = name.lastIndexOf(".");
int lastDotIndex = name.lastIndexOf(".");
if (lastDotIndex == -1) {
throw new IllegalArgumentException("'" + name + "' is not a valid method name: format is FQN.methodName");
@@ -123,17 +134,17 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
String methodName = name.substring(lastDotIndex + 1);
Assert.hasText(methodName, "Method not found for '" + name + "'");
String typeName = name.substring(0, lastDotIndex);
Class type = ClassUtils.resolveClassName(typeName, this.beanClassLoader);
addSecureMethod(type, methodName, attr);
}
/**
* Add configuration attributes for a secure method. Mapped method names can end or start with <code>&#42</code>
* for matching multiple methods.
*
*
* @param javaType target interface or class the security configuration attribute applies to
* @param mappedName mapped method name, which the javaType has declared or inherited
* @param attr required authorities associated with the method
@@ -181,38 +192,6 @@ 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.
*
@@ -236,54 +215,93 @@ public class MapBasedMethodDefinitionSource extends AbstractFallbackMethodDefini
|| (mappedName.startsWith("*") && methodName.endsWith(mappedName.substring(1, mappedName.length())));
}
public void setBeanClassLoader(ClassLoader beanClassLoader) {
Assert.notNull(beanClassLoader, "Bean class loader required");
this.beanClassLoader = beanClassLoader;
}
protected ConfigAttributeDefinition lookupAttributes(Method method) {
List attributesToReturn = new ArrayList();
/**
* @return map size (for unit tests and diagnostics)
*/
public int getMethodMapSize() {
return methodMap.size();
}
// Add attributes explicitly defined for this method invocation
merge(attributesToReturn, (ConfigAttributeDefinition) this.methodMap.get(method));
/**
* Stores both the Java Method as well as the Class we obtained the Method from. This is necessary because Method only
* provides us access to the declaring class. It doesn't provide a way for us to introspect which Class the Method
* was registered against. If a given Class inherits and redeclares a method (i.e. calls super();) the registered Class
* and declaring Class are the same. If a given class merely inherits but does not redeclare a method, the registered
* Class will be the Class we're invoking against and the Method will provide details of the declared class.
*/
private class RegisteredMethod {
private Method method;
private Class registeredJavaType;
// Add attributes explicitly defined for this method invocation's interfaces
Class[] interfaces = method.getDeclaringClass().getInterfaces();
public RegisteredMethod(Method method, Class registeredJavaType) {
Assert.notNull(method, "Method required");
Assert.notNull(registeredJavaType, "Registered Java Type required");
this.method = method;
this.registeredJavaType = registeredJavaType;
}
for (int i = 0; i < interfaces.length; i++) {
Class clazz = interfaces[i];
public boolean equals(Object obj) {
if (this == obj) {
return true;
try {
// Look for the method on the current interface
Method interfaceMethod = clazz.getDeclaredMethod(method.getName(), (Class[]) method.getParameterTypes());
ConfigAttributeDefinition interfaceAssigned =
(ConfigAttributeDefinition) this.methodMap.get(interfaceMethod);
merge(attributesToReturn, interfaceAssigned);
} catch (Exception e) {
// skip this interface
}
if (obj != null && obj instanceof RegisteredMethod) {
RegisteredMethod rhs = (RegisteredMethod) obj;
return method.equals(rhs.method) && registeredJavaType.equals(rhs.registeredJavaType);
}
return false;
}
public int hashCode() {
return method.hashCode() * registeredJavaType.hashCode();
// Return null if empty, as per abstract superclass contract
if (attributesToReturn.size() == 0) {
return null;
}
public String toString() {
return "RegisteredMethod[" + registeredJavaType.getName() + "; " + method + "]";
}
return new ConfigAttributeDefinition(attributesToReturn);
}
private void merge(List attributes, ConfigAttributeDefinition toMerge) {
if (toMerge == null) {
return;
}
attributes.addAll(toMerge.getConfigAttributes());
}
public void setBeanClassLoader(ClassLoader beanClassLoader) {
Assert.notNull(beanClassLoader, "Bean class loader required");
this.beanClassLoader = beanClassLoader;
}
/**
* @return map size (for unit tests and diagnostics)
*/
public int getMethodMapSize() {
return methodMap.size();
}
/**
* Stores both the Java Method as well as the Class we obtained the Method from. This is necessary because Method only
* provides us access to the declaring class. It doesn't provide a way for us to introspect which Class the Method
* was registered against. If a given Class inherits and redeclares a method (i.e. calls super();) the registered Class
* and declaring Class are the same. If a given class merely inherits but does not redeclare a method, the registered
* Class will be the Class we're invoking against and the Method will provide details of the declared class.
*/
private class RegisteredMethod {
private Method method;
private Class registeredJavaType;
public RegisteredMethod(Method method, Class registeredJavaType) {
Assert.notNull(method, "Method required");
Assert.notNull(registeredJavaType, "Registered Java Type required");
this.method = method;
this.registeredJavaType = registeredJavaType;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj != null && obj instanceof RegisteredMethod) {
RegisteredMethod rhs = (RegisteredMethod) obj;
return method.equals(rhs.method) && registeredJavaType.equals(rhs.registeredJavaType);
}
return false;
}
public int hashCode() {
return method.hashCode() * registeredJavaType.hashCode();
}
public String toString() {
return "RegisteredMethod[" + registeredJavaType.getName() + "; " + method + "]";
}
}
}
@@ -17,30 +17,29 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.security.ConfigAttributeDefinition;
import org.springframework.security.intercept.method.aopalliance.MethodDefinitionSourceAdvisor;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Parses AspectJ pointcut expressions, registering methods that match the pointcut with a
* traditional {@link MapBasedMethodDefinitionSource}.
*
*
* <p>
* This class provides a convenient way of declaring a list of pointcuts, and then
* having every method of every bean defined in the Spring application context compared with
* those pointcuts. Where a match is found, the matching method will be registered with the
* {@link MapBasedMethodDefinitionSource}.
* </p>
*
*
* <p>
* It is very important to understand that only the <b>first</b> pointcut that matches a given
* method will be taken as authoritative for that method. This is why pointcuts should be provided
* as a <tt>LinkedHashMap</tt>, because their order is very important.
* </p>
*
*
* <p>
* Note also that only beans defined in the Spring application context will be examined by this
* class.
* class.
* </p>
*
*
* <p>
* Because this class registers method security metadata with {@link MapBasedMethodDefinitionSource},
* normal Spring Security capabilities such as {@link MethodDefinitionSourceAdvisor} can be used.
@@ -58,18 +57,18 @@ public final class ProtectPointcutPostProcessor implements BeanPostProcessor {
private static final Log logger = LogFactory.getLog(ProtectPointcutPostProcessor.class);
private Map pointcutMap = new LinkedHashMap(); /** Key: string-based pointcut, value: ConfigAttributeDefinition */
private MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource;
private PointcutParser parser;
public ProtectPointcutPostProcessor(MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource) {
Assert.notNull(mapBasedMethodDefinitionSource, "MapBasedMethodDefinitionSource to populate is required");
this.mapBasedMethodDefinitionSource = mapBasedMethodDefinitionSource;
// Setup AspectJ pointcut expression parser
Set supportedPrimitives = new HashSet();
supportedPrimitives.add(PointcutPrimitive.EXECUTION);
supportedPrimitives.add(PointcutPrimitive.ARGS);
supportedPrimitives.add(PointcutPrimitive.REFERENCE);
private MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource;
private PointcutParser parser;
public ProtectPointcutPostProcessor(MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource) {
Assert.notNull(mapBasedMethodDefinitionSource, "MapBasedMethodDefinitionSource to populate is required");
this.mapBasedMethodDefinitionSource = mapBasedMethodDefinitionSource;
// Setup AspectJ pointcut expression parser
Set supportedPrimitives = new HashSet();
supportedPrimitives.add(PointcutPrimitive.EXECUTION);
supportedPrimitives.add(PointcutPrimitive.ARGS);
supportedPrimitives.add(PointcutPrimitive.REFERENCE);
// supportedPrimitives.add(PointcutPrimitive.THIS);
// supportedPrimitives.add(PointcutPrimitive.TARGET);
// supportedPrimitives.add(PointcutPrimitive.WITHIN);
@@ -77,90 +76,79 @@ public final class ProtectPointcutPostProcessor implements BeanPostProcessor {
// supportedPrimitives.add(PointcutPrimitive.AT_WITHIN);
// supportedPrimitives.add(PointcutPrimitive.AT_ARGS);
// supportedPrimitives.add(PointcutPrimitive.AT_TARGET);
parser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(supportedPrimitives);
}
parser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(supportedPrimitives);
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// Obtain methods for the present bean
Method[] methods;
try {
methods = bean.getClass().getMethods();
} catch (Exception e) {
throw new IllegalStateException(e.getMessage());
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// Obtain methods for the present bean
Method[] methods;
try {
methods = bean.getClass().getMethods();
} catch (Exception e) {
throw new IllegalStateException(e.getMessage());
}
// Check to see if any of those methods are compatible with our pointcut expressions
for (int i = 0; i < methods.length; i++) {
Iterator iter = pointcutMap.keySet().iterator();
while (iter.hasNext()) {
String ex = iter.next().toString();
// Parse the presented AspectJ pointcut expression
PointcutExpression expression = parser.parsePointcutExpression(ex);
// Check to see if any of those methods are compatible with our pointcut expressions
for (int i = 0; i < methods.length; i++) {
Iterator iter = pointcutMap.keySet().iterator();
while (iter.hasNext()) {
String ex = iter.next().toString();
// Parse the presented AspectJ pointcut expression
PointcutExpression expression = parser.parsePointcutExpression(ex);
// Try for the bean class directly
if (attemptMatch(bean.getClass(), methods[i], expression, beanName)) {
// We've found the first expression that matches this method, so move onto the next method now
break; // the "while" loop, not the "for" loop
}
}
}
return bean;
}
private boolean attemptMatch(Class targetClass, Method method, PointcutExpression expression, String beanName) {
// Determine if the presented AspectJ pointcut expression matches this method
boolean matches = expression.matchesMethodExecution(method).alwaysMatches();
// Handle accordingly
if (matches) {
ConfigAttributeDefinition attr = (ConfigAttributeDefinition) pointcutMap.get(expression.getPointcutExpression());
if (logger.isDebugEnabled()) {
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, attr);
}
return matches;
}
public void setPointcutMap(Map map) {
Assert.notEmpty(map);
Iterator i = map.keySet().iterator();
while (i.hasNext()) {
String expression = i.next().toString();
Object value = map.get(expression);
Assert.isInstanceOf(ConfigAttributeDefinition.class, value, "Map keys must be instances of ConfigAttributeDefinition");
addPointcut(expression, (ConfigAttributeDefinition) value);
}
}
private void addPointcut(String pointcutExpression, ConfigAttributeDefinition definition) {
Assert.hasText(pointcutExpression, "An AspectJ pointcut expression is required");
Assert.notNull(definition, "ConfigAttributeDefinition required");
pointcutExpression = replaceBooleanOperators(pointcutExpression);
pointcutMap.put(pointcutExpression, definition);
if (logger.isDebugEnabled()) {
logger.debug("AspectJ pointcut expression '" + pointcutExpression + "' registered for security configuration attribute '" + definition + "'");
}
}
/**
* @see org.springframework.aop.aspectj.AspectJExpressionPointcut#replaceBooleanOperators
*/
private String replaceBooleanOperators(String pcExpr) {
pcExpr = StringUtils.replace(pcExpr," and "," && ");
pcExpr = StringUtils.replace(pcExpr, " or ", " || ");
pcExpr = StringUtils.replace(pcExpr, " not ", " ! ");
return pcExpr;
}
// Try for the bean class directly
if (attemptMatch(bean.getClass(), methods[i], expression, beanName)) {
// We've found the first expression that matches this method, so move onto the next method now
break; // the "while" loop, not the "for" loop
}
}
}
return bean;
}
private boolean attemptMatch(Class targetClass, Method method, PointcutExpression expression, String beanName) {
// Determine if the presented AspectJ pointcut expression matches this method
boolean matches = expression.matchesMethodExecution(method).alwaysMatches();
// Handle accordingly
if (matches) {
ConfigAttributeDefinition attr = (ConfigAttributeDefinition) pointcutMap.get(expression.getPointcutExpression());
if (logger.isDebugEnabled()) {
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);
}
return matches;
}
public void setPointcutMap(Map map) {
Assert.notEmpty(map);
Iterator i = map.keySet().iterator();
while (i.hasNext()) {
String expression = i.next().toString();
Object value = map.get(expression);
Assert.isInstanceOf(ConfigAttributeDefinition.class, value, "Map keys must be instances of ConfigAttributeDefinition");
addPointcut(expression, (ConfigAttributeDefinition) value);
}
}
public void addPointcut(String pointcutExpression, ConfigAttributeDefinition definition) {
Assert.hasText(pointcutExpression, "An AspectJ pointcut expression is required");
Assert.notNull(definition, "ConfigAttributeDefinition required");
pointcutMap.put(pointcutExpression, definition);
if (logger.isDebugEnabled()) {
logger.debug("AspectJ pointcut expression '" + pointcutExpression + "' registered for security configuration attribute '" + definition + "'");
}
}
}
@@ -33,7 +33,7 @@ import org.springframework.util.Assert;
* Advisor driven by a {@link MethodDefinitionSource}, used to exclude a {@link MethodSecurityInterceptor} from
* public (ie non-secure) methods.
* <p>
* Because the AOP framework caches advice calculations, this is normally faster than just letting the
* Because the AOP framework caches advice calculations, this is normally faster than just letting the
* <code>MethodSecurityInterceptor</code> run and find out itself that it has no work to do.
* <p>
* This class also allows the use of Spring's
@@ -63,63 +63,64 @@ public class MethodDefinitionSourceAdvisor extends AbstractPointcutAdvisor imple
* @deprecated use the decoupled approach instead
*/
public MethodDefinitionSourceAdvisor(MethodSecurityInterceptor advice) {
Assert.notNull(advice.getObjectDefinitionSource(), "Cannot construct a MethodDefinitionSourceAdvisor using a " +
"MethodSecurityInterceptor that has no ObjectDefinitionSource configured");
Assert.notNull(advice.getObjectDefinitionSource(), "Cannot construct a MethodDefinitionSourceAdvisor using a " +
"MethodSecurityInterceptor that has no ObjectDefinitionSource configured");
this.interceptor = advice;
this.interceptor = advice;
this.attributeSource = advice.getObjectDefinitionSource();
}
/**
* Alternative constructor for situations where we want the advisor decoupled from the advice. Instead the advice
* bean name should be set. This prevents eager instantiation of the interceptor
* bean name should be set. This prevents eager instantiation of the interceptor
* (and hence the AuthenticationManager). See SEC-773, for example.
* <p>
* This is essentially the approach taken by subclasses of {@link AbstractBeanFactoryPointcutAdvisor}, which this
* class should extend in future. The original hierarchy and constructor have been retained for backwards
* compatibility.
*
* class should extend in future. The original hierarchy and constructor have been retained for backwards
* compatibilty.
*
* @param adviceBeanName name of the MethodSecurityInterceptor bean
* @param attributeSource the attribute source (should be the same as the one used on the interceptor)
*/
public MethodDefinitionSourceAdvisor(String adviceBeanName, MethodDefinitionSource attributeSource) {
Assert.notNull(adviceBeanName, "The adviceBeanName cannot be null");
Assert.notNull(attributeSource, "The attributeSource cannot be null");
this.adviceBeanName = adviceBeanName;
this.attributeSource = attributeSource;
Assert.notNull(adviceBeanName, "The adviceBeanName cannot be null");
Assert.notNull(attributeSource, "The attributeSource cannot be null");
this.adviceBeanName = adviceBeanName;
this.attributeSource = attributeSource;
}
//~ Methods ========================================================================================================
public Pointcut getPointcut() {
return pointcut;
}
public Pointcut getPointcut() {
return pointcut;
}
public Advice getAdvice() {
synchronized (this.adviceMonitor) {
if (interceptor == null) {
Assert.notNull(adviceBeanName, "'adviceBeanName' must be set for use with bean factory lookup.");
Assert.state(beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
interceptor = (MethodSecurityInterceptor)
beanFactory.getBean(this.adviceBeanName, MethodSecurityInterceptor.class);
}
return interceptor;
}
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public Advice getAdvice() {
synchronized (this.adviceMonitor) {
if (interceptor == null) {
Assert.notNull(adviceBeanName, "'adviceBeanName' must be set for use with bean factory lookup.");
Assert.state(beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
interceptor = (MethodSecurityInterceptor)
beanFactory.getBean(this.adviceBeanName, MethodSecurityInterceptor.class);
attributeSource = interceptor.getObjectDefinitionSource();
}
return interceptor;
}
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
//~ Inner Classes ==================================================================================================
class MethodDefinitionSourcePointcut extends StaticMethodMatcherPointcut {
public boolean matches(Method m, Class targetClass) {
return attributeSource.getAttributes(m, targetClass) != null;
}
}
/**
* Represents a <code>MethodInvocation</code>.
* <p>
@@ -152,7 +153,7 @@ public class MethodDefinitionSourceAdvisor extends AbstractPointcutAdvisor imple
}
public Object getThis() {
return this.targetClass;
return this.targetClass;
}
public Object proceed() throws Throwable {
@@ -12,5 +12,5 @@ package org.springframework.security.intercept.method.aspectj;
public interface AspectJAnnotationCallback {
//~ Methods ========================================================================================================
Object proceedWithObject() throws Throwable;
Object proceedWithObject();
}
@@ -54,16 +54,4 @@ public class RequestKey {
return method.equals(key.method);
}
public String toString() {
StringBuffer sb = new StringBuffer(url.length() + 7);
sb.append("[");
if (method != null) {
sb.append(method).append(",");
}
sb.append(url);
sb.append("]");
return sb.toString();
}
}
@@ -158,7 +158,7 @@ public final class LdapUtils {
if (url.startsWith("ldap:") || url.startsWith("ldaps:")) {
URI uri = parseLdapUrl(url);
urlRootDn = uri.getRawPath();
urlRootDn = uri.getPath();
} else {
// Assume it's an embedded server
urlRootDn = url;
@@ -15,21 +15,6 @@
package org.springframework.security.ldap;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.PartialResultException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.ldap.core.ContextExecutor;
import org.springframework.ldap.core.ContextMapper;
@@ -38,18 +23,33 @@ import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapEncoder;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.util.Assert;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import java.text.MessageFormat;
import java.util.HashSet;
import java.util.Set;
import java.util.Arrays;
/**
* Extension of Spring LDAP's LdapTemplate class which adds extra functionality required by Spring Security.
* LDAP equivalent of the Spring JdbcTemplate class.
* <p>
* This is mainly intended to simplify Ldap access within Spring Security's LDAP-related services.
* </p>
*
* @author Ben Alex
* @author Luke Taylor
* @since 2.0
*/
public class SpringSecurityLdapTemplate extends LdapTemplate {
public class SpringSecurityLdapTemplate extends org.springframework.ldap.core.LdapTemplate {
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(SpringSecurityLdapTemplate.class);
@@ -136,14 +136,14 @@ public class SpringSecurityLdapTemplate extends LdapTemplate {
* @return the set of String values for the attribute as a union of the values found in all the matching entries.
*/
public Set searchForSingleAttributeValues(final String base, final String filter, final Object[] params,
final String attributeName) {
// Escape the params acording to RFC2254
Object[] encodedParams = new String[params.length];
for (int i=0; i < params.length; i++) {
encodedParams[i] = LdapEncoder.filterEncode(params[i].toString());
}
final String attributeName) {
// Escape the params acording to RFC2254
Object[] encodedParams = new String[params.length];
for (int i=0; i < params.length; i++) {
encodedParams[i] = LdapEncoder.filterEncode(params[i].toString());
}
String formattedFilter = MessageFormat.format(filter, encodedParams);
logger.debug("Using filter: " + formattedFilter);
@@ -175,15 +175,12 @@ public class SpringSecurityLdapTemplate extends LdapTemplate {
/**
* Performs a search, with the requirement that the search shall return a single directory entry, and uses
* the supplied mapper to create the object from that entry.
* <p>
* Ignores <tt>PartialResultException</tt> if thrown, for compatibility with Active Directory
* (see {@link LdapTemplate#setIgnorePartialResultException(boolean)}).
*
* @param base the search base, relative to the base context supplied by the context source.
* @param filter the LDAP search filter
* @param params parameters to be substituted in the search.
* @param base
* @param filter
* @param params
*
* @return a DirContextOperations instance created from the matching entry.
* @return the object created by the mapper from the matching entry
*
* @throws IncorrectResultSizeDataAccessException if no results are found or the search returns more than one
* result.
@@ -191,38 +188,32 @@ public class SpringSecurityLdapTemplate extends LdapTemplate {
public DirContextOperations searchForSingleEntry(final String base, final String filter, final Object[] params) {
return (DirContextOperations) executeReadOnly(new ContextExecutor() {
public Object executeWithContext(DirContext ctx) throws NamingException {
DistinguishedName ctxBaseDn = new DistinguishedName(ctx.getNameInNamespace());
NamingEnumeration resultsEnum = ctx.search(base, filter, params, searchControls);
Set results = new HashSet();
try {
while (resultsEnum.hasMore()) {
public Object executeWithContext(DirContext ctx)
throws NamingException {
SearchResult searchResult = (SearchResult) resultsEnum.next();
// Work out the DN of the matched entry
StringBuffer dn = new StringBuffer(searchResult.getName());
NamingEnumeration results = ctx.search(base, filter, params, searchControls);
if (base.length() > 0) {
dn.append(",");
dn.append(base);
}
results.add(new DirContextAdapter(searchResult.getAttributes(),
new DistinguishedName(dn.toString()), ctxBaseDn));
}
} catch (PartialResultException e) {
logger.info("Ignoring PartialResultException");
}
if (results.size() == 0) {
if (!results.hasMore()) {
throw new IncorrectResultSizeDataAccessException(1, 0);
}
if (results.size() > 1) {
throw new IncorrectResultSizeDataAccessException(1, results.size());
SearchResult searchResult = (SearchResult) results.next();
if (results.hasMore()) {
// We don't know how many results but set to 2 which is good enough
throw new IncorrectResultSizeDataAccessException(1, 2);
}
return results.toArray()[0];
// Work out the DN of the matched entry
StringBuffer dn = new StringBuffer(searchResult.getName());
if (base.length() > 0) {
dn.append(",");
dn.append(base);
}
return new DirContextAdapter(searchResult.getAttributes(),
new DistinguishedName(dn.toString()), new DistinguishedName(ctx.getNameInNamespace()));
}
});
}
@@ -99,6 +99,8 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
*/
private GrantedAuthority defaultRole;
private ContextSource contextSource;
private SpringSecurityLdapTemplate ldapTemplate;
/**
@@ -141,10 +143,8 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
* context factory.
*/
public DefaultLdapAuthoritiesPopulator(ContextSource contextSource, String groupSearchBase) {
Assert.notNull(contextSource, "contextSource must not be null");
ldapTemplate = new SpringSecurityLdapTemplate(contextSource);
ldapTemplate.setSearchControls(searchControls);
setGroupSearchBase(groupSearchBase);
this.setContextSource(contextSource);
this.setGroupSearchBase(groupSearchBase);
}
//~ Methods ========================================================================================================
@@ -226,7 +226,20 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
}
protected ContextSource getContextSource() {
return ldapTemplate.getContextSource();
return contextSource;
}
/**
* Set the {@link ContextSource}
*
* @param contextSource supplies the contexts used to search for user roles.
*/
private void setContextSource(ContextSource contextSource) {
Assert.notNull(contextSource, "contextSource must not be null");
this.contextSource = contextSource;
ldapTemplate = new SpringSecurityLdapTemplate(contextSource);
ldapTemplate.setSearchControls(searchControls);
}
/**
@@ -144,10 +144,17 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
checkIfValidList(this.providers);
Assert.notNull(this.messages, "A message source must be set");
exceptionMappings.putAll(additionalExceptionMappings);
}
private void checkIfValidList(List listToCheck) {
if ((listToCheck == null) || (listToCheck.size() == 0)) {
throw new IllegalArgumentException("A list of AuthenticationProviders is required");
}
}
/**
* Attempts to authenticate the passed {@link Authentication} object.
* <p>
@@ -167,7 +174,7 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
* @throws AuthenticationException if authentication fails.
*/
public Authentication doAuthentication(Authentication authentication) throws AuthenticationException {
Iterator iter = getProviders().iterator();
Iterator iter = providers.iterator();
Class toTest = authentication.getClass();
@@ -266,11 +273,7 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
}
public List getProviders() {
if (providers == null || providers.size() == 0) {
throw new IllegalArgumentException("A list of AuthenticationProviders is required");
}
return providers;
return this.providers;
}
/**
@@ -300,7 +303,8 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
* AuthenticationProvider instance.
*/
public void setProviders(List providers) {
Assert.notEmpty(providers, "A list of AuthenticationProviders is required");
checkIfValidList(providers);
Iterator iter = providers.iterator();
while (iter.hasNext()) {
@@ -16,7 +16,6 @@
package org.springframework.security.providers;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.util.AuthorityUtils;
/**
@@ -35,17 +34,6 @@ public class TestingAuthenticationToken extends AbstractAuthenticationToken {
//~ Constructors ===================================================================================================
public TestingAuthenticationToken(Object principal, Object credentials) {
super(null);
this.principal = principal;
this.credentials = credentials;
}
public TestingAuthenticationToken(Object principal, Object credentials, String... authorities) {
this(principal, credentials, AuthorityUtils.stringArrayToAuthorityArray(authorities));
}
public TestingAuthenticationToken(Object principal, Object credentials, GrantedAuthority[] authorities) {
super(authorities);
this.principal = principal;
@@ -15,28 +15,30 @@
package org.springframework.security.providers.anonymous;
import org.springframework.security.SpringSecurityMessageSource;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.BadCredentialsException;
import org.springframework.security.providers.AuthenticationProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.BadCredentialsException;
import org.springframework.security.SpringSecurityMessageSource;
import org.springframework.security.providers.AuthenticationProvider;
import org.springframework.util.Assert;
/**
* An {@link AuthenticationProvider} implementation that validates {@link AnonymousAuthenticationToken}s.
* <p>
* To be successfully validated, the {@link AnonymousAuthenticationToken#getKeyHash()} must match this class'
* {@link #getKey()}.
*
* @author Ben Alex
* @version $Id$
* An {@link AuthenticationProvider} implementation that validates {@link
* org.springframework.security.providers.anonymous.AnonymousAuthenticationToken}s.<p>To be successfully validated, the
* {@link org.springframework.security.providers.anonymous.AnonymousAuthenticationToken#getKeyHash()} must match this class'
* {@link #getKey()}.</p>
*/
public class AnonymousAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(AnonymousAuthenticationProvider.class);
//~ Instance fields ================================================================================================
@@ -45,7 +47,7 @@ public class AnonymousAuthenticationProvider implements AuthenticationProvider,
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
public void afterPropertiesSet() throws Exception {
Assert.hasLength(key, "A Key is required");
Assert.notNull(this.messages, "A message source must be set");
}
@@ -45,7 +45,7 @@ import java.security.cert.X509Certificate;
*
* @author Luke Taylor
* @deprecated superceded by the preauth provider. Use the X.509 authentication support in org.springframework.security.ui.preauth.x509 instead
* or namespace support via the &lt;x509 /&gt; element.
* or namespace support via the &lt;x509 /&gt; element.
* @version $Id$
*/
public class X509AuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
@@ -61,7 +61,7 @@ public class X509AuthenticationProvider implements AuthenticationProvider, Initi
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
public void afterPropertiesSet() throws Exception {
Assert.notNull(userCache, "An x509UserCache must be set");
Assert.notNull(x509AuthoritiesPopulator, "An X509AuthoritiesPopulator must be set");
Assert.notNull(this.messages, "A message source must be set");
@@ -101,9 +101,7 @@ public class X509AuthenticationProvider implements AuthenticationProvider, Initi
UserDetails user = userCache.getUserFromCache(clientCertificate);
if (user == null) {
if (logger.isDebugEnabled()) {
logger.debug("Authenticating with certificate " + clientCertificate);
}
logger.debug("Authenticating with certificate " + clientCertificate);
user = x509AuthoritiesPopulator.getUserDetails(clientCertificate);
userCache.putUserInCache(clientCertificate, user);
}
@@ -147,11 +147,7 @@ public abstract class AbstractProcessingFilter extends SpringSecurityFilter impl
private Properties exceptionMappings = new Properties();
/**
* Delay use of NullRememberMeServices until initialization so that namespace has a chance to inject
* the RememberMeServices implementation into custom implementations.
*/
private RememberMeServices rememberMeServices = null;
private RememberMeServices rememberMeServices = new NullRememberMeServices();
private TargetUrlResolver targetUrlResolver = new TargetUrlResolverImpl();
@@ -222,13 +218,11 @@ public abstract class AbstractProcessingFilter extends SpringSecurityFilter impl
Assert.isTrue(UrlUtils.isValidRedirectUrl(filterProcessesUrl), filterProcessesUrl + " isn't a valid redirect URL");
Assert.hasLength(defaultTargetUrl, "defaultTargetUrl must be specified");
Assert.isTrue(UrlUtils.isValidRedirectUrl(defaultTargetUrl), defaultTargetUrl + " isn't a valid redirect URL");
// Assert.hasLength(authenticationFailureUrl, "authenticationFailureUrl must be specified");
Assert.isTrue(UrlUtils.isValidRedirectUrl(authenticationFailureUrl), authenticationFailureUrl + " isn't a valid redirect URL");
Assert.notNull(authenticationManager, "authenticationManager must be specified");
Assert.notNull(rememberMeServices, "rememberMeServices cannot be null");
Assert.notNull(targetUrlResolver, "targetUrlResolver cannot be null");
if (rememberMeServices == null) {
rememberMeServices = new NullRememberMeServices();
}
}
/**
@@ -35,7 +35,6 @@ import org.springframework.security.ui.WebAuthenticationDetailsSource;
import org.springframework.security.ui.AuthenticationEntryPoint;
import org.springframework.security.ui.FilterChainOrder;
import org.springframework.security.ui.SpringSecurityFilter;
import org.springframework.security.ui.rememberme.NullRememberMeServices;
import org.springframework.security.ui.rememberme.RememberMeServices;
import org.springframework.util.Assert;
@@ -92,7 +91,7 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
private AuthenticationEntryPoint authenticationEntryPoint;
private AuthenticationManager authenticationManager;
private RememberMeServices rememberMeServices = new NullRememberMeServices();
private RememberMeServices rememberMeServices;
private boolean ignoreFailure = false;
private String credentialsCharset = "UTF-8";
@@ -106,10 +105,10 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
}
}
public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
public void doFilterHttp(HttpServletRequest httpRequest, HttpServletResponse httpResponse, FilterChain chain)
throws IOException, ServletException {
String header = request.getHeader("Authorization");
String header = httpRequest.getHeader("Authorization");
if (logger.isDebugEnabled()) {
logger.debug("Authorization header: " + header);
@@ -117,7 +116,7 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
if ((header != null) && header.startsWith("Basic ")) {
byte[] base64Token = header.substring(6).getBytes("UTF-8");
String token = new String(Base64.decodeBase64(base64Token), getCredentialsCharset(request));
String token = new String(Base64.decodeBase64(base64Token), getCredentialsCharset(httpRequest));
String username = "";
String password = "";
@@ -131,7 +130,7 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
if (authenticationIsRequired(username)) {
UsernamePasswordAuthenticationToken authRequest =
new UsernamePasswordAuthenticationToken(username, password);
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
authRequest.setDetails(authenticationDetailsSource.buildDetails(httpRequest));
Authentication authResult;
@@ -145,14 +144,14 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
SecurityContextHolder.getContext().setAuthentication(null);
rememberMeServices.loginFail(request, response);
if (rememberMeServices != null) {
rememberMeServices.loginFail(httpRequest, httpResponse);
}
onUnsuccessfulAuthentication(request, response, failed);
if (ignoreFailure) {
chain.doFilter(request, response);
chain.doFilter(httpRequest, httpResponse);
} else {
authenticationEntryPoint.commence(request, response, failed);
authenticationEntryPoint.commence(httpRequest, httpResponse, failed);
}
return;
@@ -165,13 +164,13 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
SecurityContextHolder.getContext().setAuthentication(authResult);
rememberMeServices.loginSuccess(request, response, authResult);
onSuccessfulAuthentication(request, response, authResult);
if (rememberMeServices != null) {
rememberMeServices.loginSuccess(httpRequest, httpResponse, authResult);
}
}
}
chain.doFilter(request, response);
chain.doFilter(httpRequest, httpResponse);
}
private boolean authenticationIsRequired(String username) {
@@ -203,14 +202,6 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
return false;
}
protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
Authentication authResult) throws IOException {
}
protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
AuthenticationException failed) throws IOException {
}
protected AuthenticationEntryPoint getAuthenticationEntryPoint() {
return authenticationEntryPoint;
@@ -242,7 +233,6 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
}
public void setRememberMeServices(RememberMeServices rememberMeServices) {
Assert.notNull(rememberMeServices, "rememberMeServices cannot be null");
this.rememberMeServices = rememberMeServices;
}
@@ -34,10 +34,10 @@ import javax.servlet.http.HttpSession;
* @version $Id$
*/
public class SecurityContextLogoutHandler implements LogoutHandler {
private boolean invalidateHttpSession = true;
//~ Methods ========================================================================================================
private boolean invalidateHttpSession = true;
/**
* Requires the request to be passed in.
*
@@ -69,6 +69,6 @@ public class SecurityContextLogoutHandler implements LogoutHandler {
*/
public void setInvalidateHttpSession(boolean invalidateHttpSession) {
this.invalidateHttpSession = invalidateHttpSession;
}
}
}
@@ -25,13 +25,6 @@ import org.springframework.util.Assert;
/**
* Base class for processing filters that handle pre-authenticated authentication requests. Subclasses must implement
* the getPreAuthenticatedPrincipal() and getPreAuthenticatedCredentials() methods.
* <p>
* By default, the filter chain will proceed when an authentication attempt fails in order to allow other
* authentication mechanisms to process the request. To reject the credentials immediately, set the
* <tt>continueFilterChainOnUnsuccessfulAuthentication</tt> flag to false. The exception raised by the
* <tt>AuthenticationManager</tt> will the be re-thrown. Note that this will not affect cases where the principal
* returned by {@link #getPreAuthenticatedPrincipal} is null, when the chain will still proceed as normal.
*
*
* @author Luke Taylor
* @author Ruud Senden
@@ -45,8 +38,6 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends SpringSec
private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
private AuthenticationManager authenticationManager = null;
private boolean continueFilterChainOnUnsuccessfulAuthentication = true;
/**
* Check whether all required properties have been set.
@@ -97,10 +88,6 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends SpringSec
successfulAuthentication(request, response, authResult);
} catch (AuthenticationException failed) {
unsuccessfulAuthentication(request, response, failed);
if (!continueFilterChainOnUnsuccessfulAuthentication) {
throw failed;
}
}
}
@@ -156,19 +143,8 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends SpringSec
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
public void setContinueFilterChainOnUnsuccessfulAuthentication(boolean shouldContinue) {
continueFilterChainOnUnsuccessfulAuthentication = shouldContinue;
}
/**
* Override to extract the principal information from the current request
*/
protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);
/**
* Override to extract the credentials (if applicable) from the current request. Some implementations
* may return a dummy value.
*/
protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);
}
@@ -32,14 +32,14 @@ import javax.servlet.http.HttpServletResponse;
* @since 2.0
*/
public abstract class AbstractRememberMeServices implements RememberMeServices, InitializingBean, LogoutHandler {
//~ Static fields/initializers =====================================================================================
//~ Static fields/initializers =====================================================================================
public static final String SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY = "SPRING_SECURITY_REMEMBER_ME_COOKIE";
public static final String DEFAULT_PARAMETER = "_spring_security_remember_me";
private static final String DELIMITER = ":";
//~ Instance fields ================================================================================================
//~ Instance fields ================================================================================================
protected final Log logger = LogFactory.getLog(getClass());
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
@@ -49,7 +49,7 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
private String cookieName = SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY;
private String parameter = DEFAULT_PARAMETER;
private String parameter = DEFAULT_PARAMETER;
private boolean alwaysRemember;
private String key;
private int tokenValiditySeconds = 1209600; // 14 days
@@ -232,14 +232,14 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
}
String paramValue = request.getParameter(parameter);
if (paramValue != null) {
if (paramValue.equalsIgnoreCase("true") || paramValue.equalsIgnoreCase("on") ||
paramValue.equalsIgnoreCase("yes") || paramValue.equals("1")) {
return true;
}
}
if (paramValue.equalsIgnoreCase("true") || paramValue.equalsIgnoreCase("on") ||
paramValue.equalsIgnoreCase("yes") || paramValue.equals("1")) {
return true;
}
}
if (logger.isDebugEnabled()) {
logger.debug("Did not send remember-me cookie (principal did not set parameter '" + parameter + "')");
}
@@ -309,10 +309,6 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
this.cookieName = cookieName;
}
protected String getCookieName() {
return cookieName;
}
public void setAlwaysRemember(boolean alwaysRemember) {
this.alwaysRemember = alwaysRemember;
}
@@ -320,11 +316,11 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
/**
* Sets the name of the parameter which should be checked for to see if a remember-me has been requested
* during a login request. This should be the same name you assign to the checkbox in your login form.
*
*
* @param parameter the HTTP request parameter
*/
public void setParameter(String parameter) {
Assert.hasText(parameter, "Parameter name cannot be null");
Assert.hasText(parameter, "Parameter name cannot be null");
this.parameter = parameter;
}
@@ -337,7 +333,7 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
}
public void setUserDetailsService(UserDetailsService userDetailsService) {
Assert.notNull(userDetailsService, "UserDetailsService canot be null");
Assert.notNull(userDetailsService, "UserDetailsService canot be null");
this.userDetailsService = userDetailsService;
}
@@ -361,8 +357,8 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
return authenticationDetailsSource;
}
public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource cannot be null");
this.authenticationDetailsSource = authenticationDetailsSource;
}
public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource cannot be null");
this.authenticationDetailsSource = authenticationDetailsSource;
}
}
@@ -304,7 +304,8 @@ public class SwitchUserProcessingFilter extends SpringSecurityFilter implements
logger.debug("Switch User failed", failed);
if (switchFailureUrl != null) {
sendRedirect(request, response, switchFailureUrl);
switchFailureUrl = request.getContextPath() + switchFailureUrl;
response.sendRedirect(response.encodeRedirectURL(switchFailureUrl));
} else {
response.getWriter().print("Switch user failed: " + failed.getMessage());
response.flushBuffer();
@@ -25,8 +25,6 @@ import org.springframework.dao.DataAccessException;
* instead of only the directly assigned authorities.
*
* @author Michael Mayr
* @deprecated use a {@link RoleHierarchyVoter} instead of populating the user Authentication object
* with the additional authorities.
*/
public class UserDetailsServiceWrapper implements UserDetailsService {
@@ -23,7 +23,6 @@ import org.springframework.security.userdetails.UserDetails;
* delegated to the <tt>UserDetails</tt> implementation.
*
* @author Michael Mayr
* @deprecated use a {@link RoleHierarchyVoter} instead.
*/
public class UserDetailsWrapper implements UserDetails {
@@ -47,53 +47,23 @@ import javax.sql.DataSource;
/**
* <tt>UserDetailsServiceRetrieves</tt> implementation which retrieves the user details
* (username, password, enabled flag, and authorities) from a database using JDBC queries.
*
* <h3>Default Schema</h3>
* A default database schema is assumed, with two tables "users" and "authorities".
*
* <h4>The Users table</h4>
*
* This table contains the login name, password and enabled status of the user.
*
* <table>
* <tr><th>Column</th></tr>
* <tr><td>username</td></tr>
* <tr><td>password</td></tr>
* <tr><td>enabled</td></tr>
* </table>
*
* <h4>The Authorities Table</h4>
*
* <table>
* <tr><th>Column</th></tr>
* <tr><td>username</td></tr>
* <tr><td>authority</td></tr>
* </table>
*
* If you are using an existing schema you will have to set the queries <tt>usersByUsernameQuery</tt> and
* <tt>authoritiesByUsernameQuery</tt> to match your database setup
* (see {@link #DEF_USERS_BY_USERNAME_QUERY} and {@link #DEF_AUTHORITIES_BY_USERNAME_QUERY}).
*
* Retrieves user details (username, password, enabled flag, and authorities) from a JDBC location.
* <p>
* In order to minimise backward compatibility issues, this implementation doesn't recognise the expiration of user
* A default database structure is assumed, (see {@link #DEF_USERS_BY_USERNAME_QUERY} and {@link
* #DEF_AUTHORITIES_BY_USERNAME_QUERY}, which most users of this class will need to override, if using an existing
* scheme. This may be done by setting the default query strings used.
* <p>
* In order to minimise backward compatibility issues, this DAO does not recognise the expiration of user
* accounts or the expiration of user credentials. However, it does recognise and honour the user enabled/disabled
* column. This should map to a <tt>boolean</tt> type in the result set (the SQL type will depend on the
* database you are using). All the other columns map to <tt>String</tt>s.
*
* <h3>Group Support</h3>
* column.
* <p>
* Support for group-based authorities can be enabled by setting the <tt>enableGroups</tt> property to <tt>true</tt>
* (you may also then wish to set <tt>enableAuthorities</tt> to <tt>false</tt> to disable loading of authorities
* directly). With this approach, authorities are allocated to groups and a user's authorities are determined based
* on the groups they are a member of. The net result is the same (a UserDetails containing a set of
* <tt>GrantedAuthority</tt>s is loaded), but the different persistence strategy may be more suitable for the
* administration of some applications.
* <p>
* When groups are being used, the tables "groups", "group_members" and "group_authorities" are used. See
* {@link #DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY} for the default query which is used to load the group authorities.
* Again you can customize this by setting the <tt>groupAuthoritiesByUsernameQuery</tt> property, but the format of
* the rows returned should match the default.
*
*
* @author Ben Alex
* @author colin sampaleanu
@@ -184,7 +184,7 @@ public class LdapUserDetailsManager implements UserDetailsManager {
public Object executeWithContext(DirContext dirCtx) throws NamingException {
LdapContext ctx = (LdapContext) dirCtx;
ctx.removeFromEnvironment("com.sun.jndi.ldap.connect.pool");
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, LdapUtils.getFullDn(dn, ctx).toString());
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, LdapUtils.getFullDn(dn, ctx).toUrl());
ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, oldPassword);
// TODO: reconnect doesn't appear to actually change the credentials
try {
@@ -107,7 +107,6 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
/** Compiled pattern version of the filter chain map */
private Map filterChainMap;
private UrlMatcher matcher = new AntUrlPathMatcher();
private boolean stripQueryStringFromUrls = true;
private DefaultFilterInvocationDefinitionSource fids;
//~ Methods ========================================================================================================
@@ -117,8 +116,8 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
if (fids != null) {
Assert.isNull(uncompiledFilterChainMap, "Set the filterChainMap or FilterInvocationDefinitionSource but not both");
FIDSToFilterChainMapConverter converter = new FIDSToFilterChainMapConverter(fids, applicationContext);
setMatcher(converter.getMatcher());
setFilterChainMap(converter.getFilterChainMap());
setMatcher(converter.getMatcher());
setFilterChainMap(converter.getFilterChainMap());
fids = null;
}
@@ -182,16 +181,6 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
* @return an ordered array of Filters defining the filter chain
*/
public List getFilters(String url) {
if (stripQueryStringFromUrls) {
// String query string - see SEC-953
int firstQuestionMarkIndex = url.indexOf("?");
if (firstQuestionMarkIndex != -1) {
url = url.substring(0, firstQuestionMarkIndex);
}
}
Iterator filterChains = filterChainMap.entrySet().iterator();
while (filterChains.hasNext()) {
@@ -330,14 +319,6 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
return matcher;
}
/**
* If set to 'true', the query string will be stripped from the request URL before
* attempting to find a matching filter chain. This is the default value.
*/
public void setStripQueryStringFromUrls(boolean stripQueryStringFromUrls) {
this.stripQueryStringFromUrls = stripQueryStringFromUrls;
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("FilterChainProxy[");
@@ -2,22 +2,18 @@ package org.springframework.security.util;
/**
* Utilities for working with Strings and text.
*
*
* @author Luke Taylor
* @version $Id$
*/
public abstract class TextUtils {
public static String escapeEntities(String s) {
if (s == null || s.length() == 0) {
return s;
}
StringBuffer sb = new StringBuffer();
for (int i=0; i < s.length(); i++) {
char c = s.charAt(i);
if(c == '<') {
sb.append("&lt;");
} else if (c == '>') {
@@ -26,14 +22,12 @@ public abstract class TextUtils {
sb.append("&#034;");
} else if (c == '\'') {
sb.append("&#039;");
} else if (c == '&') {
sb.append("&amp;");
} else {
sb.append(c);
}
}
return sb.toString();
}
}
@@ -1,29 +0,0 @@
package org.springframework.security.vote;
import org.springframework.security.Authentication;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.userdetails.hierarchicalroles.RoleHierarchy;
import org.springframework.util.Assert;
/**
* Extended RoleVoter which uses a {@link RoleHierarchy} definition to determine the
* roles allocated to the current user before voting.
*
* @author Luke Taylor
* @since 2.0.4
*/
public class RoleHierarchyVoter extends RoleVoter {
private RoleHierarchy roleHierarchy = null;
public RoleHierarchyVoter(RoleHierarchy roleHierarchy) {
Assert.notNull(roleHierarchy, "RoleHierarchy must not be null");
this.roleHierarchy = roleHierarchy;
}
/**
* Calls the <tt>RoleHierarchy</tt> to obtain the complete set of user authorities.
*/
GrantedAuthority[] extractAuthorities(Authentication authentication) {
return roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities());
}
}
@@ -95,7 +95,6 @@ public class RoleVoter implements AccessDecisionVoter {
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
int result = ACCESS_ABSTAIN;
Iterator iter = config.getConfigAttributes().iterator();
GrantedAuthority[] authorities = extractAuthorities(authentication);
while (iter.hasNext()) {
ConfigAttribute attribute = (ConfigAttribute) iter.next();
@@ -103,6 +102,7 @@ public class RoleVoter implements AccessDecisionVoter {
if (this.supports(attribute)) {
result = ACCESS_DENIED;
GrantedAuthority[] authorities = authentication.getAuthorities();
// Attempt to find a matching granted authority
for (int i = 0; i < authorities.length; i++) {
if (attribute.getAttribute().equals(authorities[i].getAuthority())) {
@@ -114,8 +114,4 @@ public class RoleVoter implements AccessDecisionVoter {
return result;
}
GrantedAuthority[] extractAuthorities(Authentication authentication) {
return authentication.getAuthorities();
}
}
@@ -1,5 +1,3 @@
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-2.0.4.xsd
http\://www.springframework.org/schema/security/spring-security-2.0.xsd=org/springframework/security/config/spring-security-2.0.xsd
http\://www.springframework.org/schema/security/spring-security-2.0.1.xsd=org/springframework/security/config/spring-security-2.0.1.xsd
http\://www.springframework.org/schema/security/spring-security-2.0.2.xsd=org/springframework/security/config/spring-security-2.0.2.xsd
http\://www.springframework.org/schema/security/spring-security-2.0.4.xsd=org/springframework/security/config/spring-security-2.0.4.xsd
@@ -46,7 +46,6 @@ password-encoder.attlist &=
ref | (hash? & base64?)
salt-source =
## Password salting strategy. A system-wide constant or a property from the UserDetails object can be used.
element salt-source {user-property | system-wide}
user-property =
## A property of the UserDetails object which will be used as salt by a password encoder. Typically something like "username" might be used.
@@ -70,8 +69,8 @@ ldap-server.attlist &= (url | port)?
ldap-server.attlist &=
## Username (DN) of the "manager" user identity which will be used to authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used.
attribute manager-dn {xsd:string}?
ldap-server.attlist &=
## The password for the manager DN.
ldap-server.attlist &=
attribute manager-password {xsd:string}?
ldap-server.attlist &=
## Explicitly specifies an ldif file resource to load into an embedded LDAP server
@@ -89,13 +88,12 @@ group-search-filter-attribute =
## Group search filter. Defaults to (uniqueMember={0}). The substituted parameter is the DN of the user.
attribute group-search-filter {xsd:string}
group-search-base-attribute =
## Search base for group membership searches. Defaults to "" (searching from the root).
## Search base for group membership searches. Defaults to "ou=groups".
attribute group-search-base {xsd:string}
user-search-filter-attribute =
## The LDAP filter used to search for users (optional). For example "(uid={0})". The substituted parameter is the user's login name.
attribute user-search-filter {xsd:string}
user-search-base-attribute =
## Search base for user searches. Defaults to "". Only used with a 'user-search-filter'.
## Search base for user searches. Defaults to "".
attribute user-search-base {xsd:string}
group-role-attribute-attribute =
## The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn".
@@ -193,7 +191,6 @@ global-method-security.attlist &=
attribute access-decision-manager-ref {xsd:string}?
custom-after-invocation-provider =
## Used to decorate an AfterInvocationProvider to specify that it should be used with method security.
element custom-after-invocation-provider {empty}
protect-pointcut =
@@ -261,7 +258,7 @@ intercept-url.attlist &=
## The filter list for the path. Currently can be set to "none" to remove a path from having any filters applied. The full filter stack (consisting of all filters created by the namespace configuration, and any added using 'custom-filter'), will be applied to any other paths.
attribute filters {"none"}?
intercept-url.attlist &=
## Used to specify that a URL must be accessed over http or https, or that there is no preference.
## Used to specify that a URL must be accessed over http or https
attribute requires-channel {"http" | "https" | "any"}?
logout =
@@ -336,13 +333,12 @@ concurrent-session-control =
## Adds support for concurrent session control, allowing limits to be placed on the number of sessions a user can have.
element concurrent-session-control {concurrent-sessions.attlist, empty}
concurrent-sessions.attlist &=
## The maximum number of sessions a single user can have open at the same time. Defaults to "1".
attribute max-sessions {xsd:positiveInteger}?
concurrent-sessions.attlist &=
## The URL a user will be redirected to if they attempt to use a session which has been "expired" by the concurrent session controller because they have logged in again.
## The URL a user will be redirected to if they attempt to use a session which has been "expired" by the concurrent session controller.
attribute expired-url {xsd:string}?
concurrent-sessions.attlist &=
## Specifies that an exception should be raised when a user attempts to login when they already have the maximum configured sessions open. The default behaviour is to expire the original session.
## Specifies that an exception should be raised when a user attempts to login twice. The default behaviour is to expire the original session.
attribute exception-if-maximum-exceeded {boolean}?
concurrent-sessions.attlist &=
## Allows you to define an alias for the SessionRegistry bean in order to access it in your own configuration
@@ -375,7 +371,7 @@ remember-me-services-ref =
## Allows a custom implementation of RememberMeServices to be used. Note that this implementation should return RememberMeAuthenticationToken instances with the same "key" value as specified in the remember-me element. Alternatively it should register its own AuthenticationProvider.
attribute services-ref {xsd:string}?
remember-me-data-source-ref =
## DataSource bean for the database that contains the token repository schema.
## DataSource bean for the database that contains the token
data-source-ref
anonymous =
@@ -400,9 +396,9 @@ port-mappings.attlist &= empty
port-mapping =
element port-mapping {http-port, https-port}
http-port = attribute http {xsd:string}
http-port = attribute http {xsd:integer}
https-port = attribute https {xsd:string}
https-port = attribute https {xsd:integer}
x509 =
@@ -434,7 +430,6 @@ ap.attlist &=
user-service-ref?
custom-authentication-provider =
## Element used to decorate an AuthenticationProvider bean to add it to the internal AuthenticationManager maintained by the namespace.
element custom-authentication-provider {cap.attlist}
cap.attlist &= empty
@@ -501,6 +496,6 @@ position =
named-security-filter = "FIRST" | "CHANNEL_FILTER" | "CONCURRENT_SESSION_FILTER" | "SESSION_CONTEXT_INTEGRATION_FILTER" | "LOGOUT_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_PROCESSING_FILTER" | "AUTHENTICATION_PROCESSING_FILTER" | "OPENID_PROCESSING_FILTER" |"BASIC_PROCESSING_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "NTLM_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"
named-security-filter = "FIRST" | "CHANNEL_FILTER" | "CONCURRENT_SESSION_FILTER" | "SESSION_CONTEXT_INTEGRATION_FILTER" | "LOGOUT_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_PROCESSING_FILTER" | "AUTHENTICATION_PROCESSING_FILTER" | "BASIC_PROCESSING_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "NTLM_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"
@@ -222,7 +222,7 @@
<xs:attribute name="group-search-base" use="required" type="xs:string">
<xs:annotation>
<xs:documentation>Search base for group membership searches. Defaults to
"" (searching from the root).</xs:documentation>
"ou=groups".</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
@@ -1,53 +0,0 @@
AuthByAdapterProvider.incorrectKey=La actual implementación de AuthByAdapter no contiene la clave esperada
BasicAclEntryAfterInvocationProvider.noPermission=Authentication {0} NO tiene permisos para el objeto de dominio {1}
BasicAclEntryAfterInvocationProvider.insufficientPermission=Authentication {0} tiene permisos ACL para objeto de dominio, pero no los permisos ACL requeridos para el objeto de dominio {1}
ConcurrentSessionControllerImpl.exceededAllowed=Sesiones máximas de {0} para esta Identificación excedidas
ProviderManager.providerNotFound=AuthenticationProvider no encontrado para {0}
AnonymousAuthenticationProvider.incorrectKey=El actual AnonymousAuthenticationToken no contiene la clave esperada
CasAuthenticationProvider.incorrectKey=El actual CasAuthenticationToken no contiene la clave esperada
CasAuthenticationProvider.noServiceTicket=No se ha podido proporcionar un billete de servicio CAS para validar
NamedCasProxyDecider.untrusted=El proxy más cercano {0} no es confiable
RejectProxyTickets.reject=Las entradas del proxy han sido rechazadas
AbstractSecurityInterceptor.authenticationNotFound=El objeto Authentication no ha sido encontrado en el SecurityContext
AbstractUserDetailsAuthenticationProvider.onlySupports=Sólo UsernamePasswordAuthenticationToken es soportada
AbstractUserDetailsAuthenticationProvider.locked=La cuenta del usuario está bloqueada
AbstractUserDetailsAuthenticationProvider.disabled=El usuario está deshabilitado
AbstractUserDetailsAuthenticationProvider.expired=La cuenta del usuario ha expirado
AbstractUserDetailsAuthenticationProvider.credentialsExpired=Las credenciales del usuario han expirado
AbstractUserDetailsAuthenticationProvider.badCredentials=Credenciales erróneas
X509AuthenticationProvider.certificateNull=Cerfificado nulo
DaoX509AuthoritiesPopulator.noMatching=No se ha encontrado un patrón coincidente en subjectDN: {0}
RememberMeAuthenticationProvider.incorrectKey=El actual RememberMeAuthenticationToken no contiene la clave esperada
RunAsImplAuthenticationProvider.incorrectKey=El actual RunAsUserToken no contiene la clave esperada
DigestProcessingFilter.missingMandatory=Valor digest obligatorio perdido; header recibido {0}
DigestProcessingFilter.missingAuth=Valor digest obligatorio perdido para 'auth' QOP; header recibido {0}
DigestProcessingFilter.incorrectRealm=Respuesta realm de nombre {0} no coincide con realm del sistema de nombre {1}
DigestProcessingFilter.nonceExpired=Nonce ha expirado/fuera de tiempo
DigestProcessingFilter.nonceEncoding=Nonce no está codificado en Base64; nonce recibido {0}
DigestProcessingFilter.nonceNotTwoTokens=Nonce token debería tener dos fichas pero tenía {0}
DigestProcessingFilter.nonceNotNumeric=Nonce token debería tener primero un token numérico, pero tenía {0}
DigestProcessingFilter.nonceCompromised=Nonce token comprometido {0}
DigestProcessingFilter.usernameNotFound=Usuario y nombre {0} no encontrado
DigestProcessingFilter.incorrectResponse=Respuesta incorrecta
JdbcDaoImpl.notFound=Usuario {0} no encontrado
JdbcDaoImpl.noAuthority=Usuario {0} no tiene GrantedAuthority
SwitchUserProcessingFilter.noCurrentUser=No hay usuario actual asociado con esta petición
SwitchUserProcessingFilter.noOriginalAuthentication=No se puede encontrar el objeto Authentication original
SwitchUserProcessingFilter.usernameNotFound=Usuario y nombre {0} no encontrado
SwitchUserProcessingFilter.locked=La cuenta del usuario está bloqueada
SwitchUserProcessingFilter.disabled=El usuario está deshabilitado
SwitchUserProcessingFilter.expired=La cuenta del usuario ha expirado
SwitchUserProcessingFilter.credentialsExpired=Las credenciales del usuario han expirado
AbstractAccessDecisionManager.accessDenied=Acceso denegado
LdapAuthenticationProvider.emptyUsername=Usuario y nombre no permitido
LdapAuthenticationProvider.emptyPassword=Credenciales erróneas
DefaultIntitalDirContextFactory.communicationFailure=No se puede conectar con el servidor LDAP
DefaultIntitalDirContextFactory.badCredentials=Credenciales erróneas
DefaultIntitalDirContextFactory.unexpectedException=Error al obtener el InitialDirContext debido a una excepción inesperada
PasswordComparisonAuthenticator.badCredentials=Credenciales erróneas
BindAuthenticator.badCredentials=Credenciales erróneas
BindAuthenticator.failedToLoadAttributes=Credenciales erróneas
UserDetailsService.locked=La cuenta del usuario está bloqueada
UserDetailsService.disabled=El usuario está deshabilitado
UserDetailsService.expired=La cuenta del usuario ha expirado
UserDetailsService.credentialsExpired=Las credenciales del usuario han expirado
@@ -6,12 +6,12 @@ ProviderManager.providerNotFound=\u672a\u67e5\u627e\u5230\u9488\u5bf9{0}\u7684Au
AnonymousAuthenticationProvider.incorrectKey=\u5c55\u793a\u7684AnonymousAuthenticationToken\u4e0d\u542b\u6709\u9884\u671f\u7684key
CasAuthenticationProvider.incorrectKey=\u5c55\u793a\u7684CasAuthenticationToken\u4e0d\u542b\u6709\u9884\u671f\u7684key
CasAuthenticationProvider.noServiceTicket=\u672a\u80fd\u591f\u6b63\u786e\u63d0\u4f9b\u5f85\u9a8c\u8bc1\u7684CAS\u670d\u52a1\u7968\u6839
NamedCasProxyDecider.untrusted=\u4ee3\u7406({0})\u4e0d\u53d7\u4fe1\u4efb
NamedCasProxyDecider.untrusted=\u4ee3\u7406({0}) \u4e0d\u53d7\u4fe1\u4efb
RejectProxyTickets.reject=Proxy\u7968\u6839\u88ab\u62d2\u7edd
AbstractSecurityInterceptor.authenticationNotFound=\u672a\u5728SecurityContext\u4e2d\u67e5\u627e\u5230\u8ba4\u8bc1\u5bf9\u8c61
AbstractUserDetailsAuthenticationProvider.onlySupports=\u4ec5\u4ec5\u652f\u6301UsernamePasswordAuthenticationToken
AbstractUserDetailsAuthenticationProvider.locked=\u7528\u6237\u5e10\u53f7\u5df2\u88ab\u9501\u5b9a
AbstractUserDetailsAuthenticationProvider.disabled=\u7528\u6237\u5df2\u5931\u6548
AbstractUserDetailsAuthenticationProvider.disabled=\u7528\u6237\u5df2\u88ab\u5931\u6548
AbstractUserDetailsAuthenticationProvider.expired=\u7528\u6237\u5e10\u53f7\u5df2\u8fc7\u671f
AbstractUserDetailsAuthenticationProvider.credentialsExpired=\u7528\u6237\u51ed\u8bc1\u5df2\u8fc7\u671f
AbstractUserDetailsAuthenticationProvider.badCredentials=\u574f\u7684\u51ed\u8bc1
@@ -29,13 +29,11 @@ DigestProcessingFilter.nonceNotNumeric=Nonce\u4ee4\u724c\u7684\u7b2c1\u90e8\u520
DigestProcessingFilter.nonceCompromised=Nonce\u4ee4\u724c\u5df2\u7ecf\u5b58\u5728\u95ee\u9898\u4e86\uff0c{0}
DigestProcessingFilter.usernameNotFound=\u7528\u6237\u540d{0}\u672a\u627e\u5230
DigestProcessingFilter.incorrectResponse=\u9519\u8bef\u7684\u54cd\u5e94\u7ed3\u679c
JdbcDaoImpl.notFound=\u672a\u627e\u5230\u7528\u6237{0}
JdbcDaoImpl.noAuthority=\u6ca1\u6709\u4e3a\u7528\u6237{0}\u6307\u5b9a\u89d2\u8272
SwitchUserProcessingFilter.noCurrentUser=\u4e0d\u5b58\u5728\u5f53\u524d\u7528\u6237
SwitchUserProcessingFilter.noOriginalAuthentication=\u4e0d\u80fd\u591f\u67e5\u627e\u5230\u539f\u5148\u7684\u5df2\u8ba4\u8bc1\u5bf9\u8c61
SwitchUserProcessingFilter.usernameNotFound=\u7528\u6237\u540d{0}\u672a\u627e\u5230
SwitchUserProcessingFilter.locked=\u7528\u6237\u5e10\u53f7\u5df2\u88ab\u9501\u5b9a
SwitchUserProcessingFilter.disabled=\u7528\u6237\u5df2\u5931\u6548
SwitchUserProcessingFilter.disabled=\u7528\u6237\u5df2\u88ab\u5931\u6548
SwitchUserProcessingFilter.expired=\u7528\u6237\u5e10\u53f7\u5df2\u8fc7\u671f
SwitchUserProcessingFilter.credentialsExpired=\u7528\u6237\u51ed\u8bc1\u5df2\u8fc7\u671f
AbstractAccessDecisionManager.accessDenied=\u4e0d\u5141\u8bb8\u8bbf\u95ee
@@ -47,8 +45,4 @@ DefaultIntitalDirContextFactory.unexpectedException=\u7531\u4e8e\u672a\u9884\u67
PasswordComparisonAuthenticator.badCredentials=\u574f\u7684\u51ed\u8bc1
BindAuthenticator.badCredentials=\u574f\u7684\u51ed\u8bc1
BindAuthenticator.failedToLoadAttributes=\u574f\u7684\u51ed\u8bc1
UserDetailsService.locked=\u7528\u6237\u5e10\u53f7\u5df2\u88ab\u9501\u5b9a
UserDetailsService.disabled=\u7528\u6237\u5df2\u5931\u6548
UserDetailsService.expired=\u7528\u6237\u5e10\u53f7\u5df2\u8fc7\u671f
UserDetailsService.credentialsExpired=\u7528\u6237\u51ed\u8bc1\u5df2\u8fc7\u671f
@@ -15,9 +15,7 @@
package org.springframework.security;
import static org.junit.Assert.*;
import org.junit.Test;
import junit.framework.TestCase;
/**
@@ -26,10 +24,28 @@ import org.junit.Test;
* @author Ben Alex
* @version $Id$
*/
public class GrantedAuthorityImplTests {
@Test
public void equalsBehavesAsExpected() throws Exception {
public class GrantedAuthorityImplTests extends TestCase {
//~ Constructors ===================================================================================================
public GrantedAuthorityImplTests() {
super();
}
public GrantedAuthorityImplTests(String arg0) {
super(arg0);
}
//~ Methods ========================================================================================================
public static void main(String[] args) {
junit.textui.TestRunner.run(GrantedAuthorityImplTests.class);
}
public final void setUp() throws Exception {
super.setUp();
}
public void testObjectEquals() throws Exception {
GrantedAuthorityImpl auth1 = new GrantedAuthorityImpl("TEST");
GrantedAuthorityImpl auth2 = new GrantedAuthorityImpl("TEST");
assertEquals(auth1, auth2);
@@ -43,52 +59,32 @@ public class GrantedAuthorityImplTests {
GrantedAuthorityImpl auth3 = new GrantedAuthorityImpl("NOT_EQUAL");
assertTrue(!auth1.equals(auth3));
MockGrantedAuthority mock1 = new MockGrantedAuthority("TEST");
MockGrantedAuthorityImpl mock1 = new MockGrantedAuthorityImpl("TEST");
assertEquals(auth1, mock1);
MockGrantedAuthority mock2 = new MockGrantedAuthority("NOT_EQUAL");
MockGrantedAuthorityImpl mock2 = new MockGrantedAuthorityImpl("NOT_EQUAL");
assertTrue(!auth1.equals(mock2));
Integer int1 = new Integer(222);
assertTrue(!auth1.equals(int1));
}
@Test
public void toStringReturnsAuthorityValue() {
public void testToString() {
GrantedAuthorityImpl auth = new GrantedAuthorityImpl("TEST");
assertEquals("TEST", auth.toString());
}
@Test
public void compareToGrantedAuthorityWithSameValueReturns0() {
assertEquals(0, new GrantedAuthorityImpl("TEST").compareTo(new MockGrantedAuthority("TEST")));
}
@Test
public void compareToNullReturnsNegativeOne() {
assertEquals(-1, new GrantedAuthorityImpl("TEST").compareTo(null));
}
/* SEC-899 */
@Test
public void compareToHandlesCustomAuthorityWhichReturnsNullFromGetAuthority() {
assertEquals(-1, new GrantedAuthorityImpl("TEST").compareTo(new MockGrantedAuthority()));
}
//~ Inner Classes ==================================================================================================
private class MockGrantedAuthority implements GrantedAuthority {
private class MockGrantedAuthorityImpl implements GrantedAuthority, Comparable {
private String role;
public MockGrantedAuthority() {
}
public MockGrantedAuthority(String role) {
public MockGrantedAuthorityImpl(String role) {
this.role = role;
}
public int compareTo(Object o) {
throw new UnsupportedOperationException();
return this.role.compareTo(((GrantedAuthority)o).getAuthority());
}
public String getAuthority() {
@@ -1,232 +0,0 @@
package org.springframework.security.authoritymapping;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import junit.framework.TestCase;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
/**
*
* @author Ruud Senden
*/
public class MapBasedAttributes2GrantedAuthoritiesMapperTest extends TestCase {
protected void setUp() throws Exception {
// Set Log4j loglevel to debug to include all logstatements in tests
Logger.getRootLogger().setLevel(Level.DEBUG);
}
public final void testAfterPropertiesSetNoMap() {
MapBasedAttributes2GrantedAuthoritiesMapper mapper = new MapBasedAttributes2GrantedAuthoritiesMapper();
try {
mapper.afterPropertiesSet();
fail("Expected exception not thrown");
} catch (IllegalArgumentException expected) {
// Expected exception
} catch (Exception unexpected) {
fail("Unexpected exception: " + unexpected);
}
}
public final void testAfterPropertiesSetEmptyMap() {
MapBasedAttributes2GrantedAuthoritiesMapper mapper = new MapBasedAttributes2GrantedAuthoritiesMapper();
mapper.setAttributes2grantedAuthoritiesMap(new HashMap());
try {
mapper.afterPropertiesSet();
fail("Expected exception not thrown");
} catch (IllegalArgumentException expected) {
// Expected exception
} catch (Exception unexpected) {
fail("Unexpected exception: " + unexpected);
}
}
public final void testAfterPropertiesSetInvalidKeyTypeMap() {
MapBasedAttributes2GrantedAuthoritiesMapper mapper = new MapBasedAttributes2GrantedAuthoritiesMapper();
HashMap m = new HashMap();
m.put(new Object(),"ga1");
mapper.setAttributes2grantedAuthoritiesMap(m);
try {
mapper.afterPropertiesSet();
fail("Expected exception not thrown");
} catch (IllegalArgumentException expected) {
// Expected exception
} catch (Exception unexpected) {
fail("Unexpected exception: " + unexpected);
}
}
public final void testAfterPropertiesSetInvalidValueTypeMap1() {
MapBasedAttributes2GrantedAuthoritiesMapper mapper = new MapBasedAttributes2GrantedAuthoritiesMapper();
HashMap m = new HashMap();
m.put("role1",new Object());
mapper.setAttributes2grantedAuthoritiesMap(m);
try {
mapper.afterPropertiesSet();
fail("Expected exception not thrown");
} catch (IllegalArgumentException expected) {
// Expected exception
} catch (Exception unexpected) {
fail("Unexpected exception: " + unexpected);
}
}
public final void testAfterPropertiesSetInvalidValueTypeMap2() {
MapBasedAttributes2GrantedAuthoritiesMapper mapper = new MapBasedAttributes2GrantedAuthoritiesMapper();
HashMap m = new HashMap();
m.put("role1",new Object[]{new String[]{"ga1","ga2"}, new Object()});
mapper.setAttributes2grantedAuthoritiesMap(m);
try {
mapper.afterPropertiesSet();
fail("Expected exception not thrown");
} catch (IllegalArgumentException expected) {
// Expected exception
} catch (Exception unexpected) {
fail("Unexpected exception: " + unexpected);
}
}
public final void testAfterPropertiesSetValidMap() {
MapBasedAttributes2GrantedAuthoritiesMapper mapper = new MapBasedAttributes2GrantedAuthoritiesMapper();
HashMap m = getValidAttributes2GrantedAuthoritiesMap();
mapper.setAttributes2grantedAuthoritiesMap(m);
try {
mapper.afterPropertiesSet();
} catch (Exception unexpected) {
fail("Unexpected exception: " + unexpected);
}
}
public final void testMapping1() {
String[] roles = { "role1" };
String[] expectedGas = { "ga1" };
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
testGetGrantedAuthorities(mapper, roles, expectedGas);
}
public final void testMapping2() {
String[] roles = { "role2" };
String[] expectedGas = { "ga2" };
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
testGetGrantedAuthorities(mapper, roles, expectedGas);
}
public final void testMapping3() {
String[] roles = { "role3" };
String[] expectedGas = { "ga3", "ga4" };
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
testGetGrantedAuthorities(mapper, roles, expectedGas);
}
public final void testMapping4() {
String[] roles = { "role4" };
String[] expectedGas = { "ga5", "ga6" };
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
testGetGrantedAuthorities(mapper, roles, expectedGas);
}
public final void testMapping5() {
String[] roles = { "role5" };
String[] expectedGas = { "ga7", "ga8", "ga9" };
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
testGetGrantedAuthorities(mapper, roles, expectedGas);
}
public final void testMapping6() {
String[] roles = { "role6" };
String[] expectedGas = { "ga10", "ga11", "ga12" };
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
testGetGrantedAuthorities(mapper, roles, expectedGas);
}
public final void testMapping7() {
String[] roles = { "role7" };
String[] expectedGas = { "ga13", "ga14" };
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
testGetGrantedAuthorities(mapper, roles, expectedGas);
}
public final void testMapping8() {
String[] roles = { "role8" };
String[] expectedGas = { "ga13", "ga14" };
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
testGetGrantedAuthorities(mapper, roles, expectedGas);
}
public final void testMapping9() {
String[] roles = { "role9" };
String[] expectedGas = {};
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
testGetGrantedAuthorities(mapper, roles, expectedGas);
}
public final void testMapping10() {
String[] roles = { "role10" };
String[] expectedGas = {};
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
testGetGrantedAuthorities(mapper, roles, expectedGas);
}
public final void testMapping11() {
String[] roles = { "role11" };
String[] expectedGas = {};
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
testGetGrantedAuthorities(mapper, roles, expectedGas);
}
public final void testNonExistingMapping() {
String[] roles = { "nonExisting" };
String[] expectedGas = {};
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
testGetGrantedAuthorities(mapper, roles, expectedGas);
}
public final void testMappingCombination() {
String[] roles = { "role1", "role2", "role3", "role4", "role5", "role6", "role7", "role8", "role9", "role10", "role11" };
String[] expectedGas = { "ga1", "ga2", "ga3", "ga4", "ga5", "ga6", "ga7", "ga8", "ga9", "ga10", "ga11", "ga12", "ga13", "ga14"};
Attributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
testGetGrantedAuthorities(mapper, roles, expectedGas);
}
private HashMap getValidAttributes2GrantedAuthoritiesMap() {
HashMap m = new HashMap();
m.put("role1","ga1");
m.put("role2",new GrantedAuthorityImpl("ga2"));
m.put("role3",Arrays.asList(new Object[]{"ga3",new GrantedAuthorityImpl("ga4")}));
m.put("role4","ga5,ga6");
m.put("role5",Arrays.asList(new Object[]{"ga7","ga8",new Object[]{new GrantedAuthorityImpl("ga9")}}));
m.put("role6",new Object[]{"ga10","ga11",new Object[]{new GrantedAuthorityImpl("ga12")}});
m.put("role7",new String[]{"ga13","ga14"});
m.put("role8",new String[]{"ga13","ga14",null});
m.put("role9",null);
m.put("role10",new Object[]{});
m.put("role11",Arrays.asList(new Object[]{null}));
return m;
}
private MapBasedAttributes2GrantedAuthoritiesMapper getDefaultMapper() {
MapBasedAttributes2GrantedAuthoritiesMapper mapper = new MapBasedAttributes2GrantedAuthoritiesMapper();
mapper.setAttributes2grantedAuthoritiesMap(getValidAttributes2GrantedAuthoritiesMap());
mapper.afterPropertiesSet();
return mapper;
}
private void testGetGrantedAuthorities(Attributes2GrantedAuthoritiesMapper mapper, String[] roles, String[] expectedGas) {
GrantedAuthority[] result = mapper.getGrantedAuthorities(roles);
Collection resultColl = new ArrayList(result.length);
for (int i = 0; i < result.length; i++) {
resultColl.add(result[i].getAuthority());
}
Collection expectedColl = Arrays.asList(expectedGas);
assertTrue("Role collections do not match; result: " + resultColl + ", expected: " + expectedColl, expectedColl
.containsAll(resultColl)
&& resultColl.containsAll(expectedColl));
}
}
@@ -28,7 +28,7 @@ import java.util.Random;
* @author Luke Taylor
* @version $Id$
*/
public class SessionRegistryImplMTTests extends TestCase {
public class SessionRegistryImplMultithreadedTests extends TestCase {
private static final Random rnd = new Random();
private static boolean errorOccurred;
@@ -1,13 +0,0 @@
package org.springframework.security.config;
public abstract class ConfigTestUtils {
public static final String AUTH_PROVIDER_XML =
" <authentication-provider>" +
" <user-service id='us'>" +
" <user name='bob' password='bobspassword' authorities='ROLE_A,ROLE_B' />" +
" <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>" +
" </authentication-provider>";
}
@@ -11,7 +11,7 @@ import org.springframework.security.util.InMemoryXmlApplicationContext;
public class CustomAfterInvocationProviderBeanDefinitionDecoratorTests {
private AbstractXmlApplicationContext appContext;
@After
public void closeAppContext() {
if (appContext != null) {
@@ -19,7 +19,7 @@ public class CustomAfterInvocationProviderBeanDefinitionDecoratorTests {
appContext = null;
}
}
@Test
public void customAfterInvocationProviderIsAddedToInterceptor() {
setContext(
@@ -27,11 +27,11 @@ public class CustomAfterInvocationProviderBeanDefinitionDecoratorTests {
"<b:bean id='aip' class='org.springframework.security.config.MockAfterInvocationProvider'>" +
" <custom-after-invocation-provider />" +
"</b:bean>" +
ConfigTestUtils.AUTH_PROVIDER_XML
HttpSecurityBeanDefinitionParserTests.AUTH_PROVIDER_XML
);
MethodSecurityInterceptor msi = (MethodSecurityInterceptor) appContext.getBean(BeanIds.METHOD_SECURITY_INTERCEPTOR);
AfterInvocationProviderManager apm = (AfterInvocationProviderManager) msi.getAfterInvocationManager();
AfterInvocationProviderManager apm = (AfterInvocationProviderManager) msi.getAfterInvocationManager();
assertNotNull(apm);
assertEquals(1, apm.getProviders().size());
assertTrue(apm.getProviders().get(0) instanceof MockAfterInvocationProvider);
@@ -15,36 +15,36 @@ import org.springframework.security.intercept.web.FilterInvocation;
import org.springframework.security.util.InMemoryXmlApplicationContext;
/**
*
*
* @author Luke Taylor
* @version $Id$
*/
public class FilterInvocationDefinitionSourceParserTests {
private AbstractXmlApplicationContext appContext;
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
appContext = null;
}
}
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
}
@Test
public void parsingMinimalConfigurationIsSuccessful() {
setContext(
"<filter-invocation-definition-source id='fids'>" +
" <intercept-url pattern='/**' access='ROLE_A'/>" +
"</filter-invocation-definition-source>");
" <intercept-url pattern='/**' access='ROLE_A'/>" +
"</filter-invocation-definition-source>");
DefaultFilterInvocationDefinitionSource fids = (DefaultFilterInvocationDefinitionSource) appContext.getBean("fids");
ConfigAttributeDefinition cad = fids.getAttributes(createFilterInvocation("/anything", "GET"));
assertTrue(cad.contains(new SecurityConfig("ROLE_A")));
}
@Test
public void parsingWithinFilterSecurityInterceptorIsSuccessful() {
setContext(
@@ -57,12 +57,12 @@ public class FilterInvocationDefinitionSourceParserTests {
" <intercept-url pattern='/**' access='ROLE_USER'/>" +
" </filter-invocation-definition-source>" +
" </b:property>" +
"</b:bean>" + ConfigTestUtils.AUTH_PROVIDER_XML);
"</b:bean>" + HttpSecurityBeanDefinitionParserTests.AUTH_PROVIDER_XML);
}
private FilterInvocation createFilterInvocation(String path, String method) {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI(null);
@@ -1,7 +1,6 @@
package org.springframework.security.config;
import static org.junit.Assert.*;
import static org.springframework.security.config.ConfigTestUtils.*;
import java.lang.reflect.Method;
import java.util.Iterator;
@@ -35,7 +34,6 @@ import org.springframework.security.ui.SessionFixationProtectionFilter;
import org.springframework.security.ui.WebAuthenticationDetails;
import org.springframework.security.ui.basicauth.BasicProcessingFilter;
import org.springframework.security.ui.logout.LogoutFilter;
import org.springframework.security.ui.logout.LogoutHandler;
import org.springframework.security.ui.preauth.x509.X509PreAuthenticatedProcessingFilter;
import org.springframework.security.ui.rememberme.NullRememberMeServices;
import org.springframework.security.ui.rememberme.PersistentTokenBasedRememberMeServices;
@@ -57,7 +55,13 @@ import org.springframework.util.ReflectionUtils;
*/
public class HttpSecurityBeanDefinitionParserTests {
private AbstractXmlApplicationContext appContext;
static final String AUTH_PROVIDER_XML =
" <authentication-provider>" +
" <user-service id='us'>" +
" <user name='bob' password='bobspassword' authorities='ROLE_A,ROLE_B' />" +
" <user name='bill' password='billspassword' authorities='ROLE_A,ROLE_B,AUTH_OTHER' />" +
" </user-service>" +
" </authentication-provider>";
@After
public void closeAppContext() {
@@ -71,7 +75,7 @@ public class HttpSecurityBeanDefinitionParserTests {
public void minimalConfigurationParses() {
setContext("<http><http-basic /></http>" + AUTH_PROVIDER_XML);
}
@Test
public void httpAutoConfigSetsUpCorrectFilterList() throws Exception {
setContext("<http auto-config='true' />" + AUTH_PROVIDER_XML);
@@ -79,26 +83,24 @@ public class HttpSecurityBeanDefinitionParserTests {
List filterList = getFilters("/anyurl");
checkAutoConfigFilters(filterList);
assertEquals(true, FieldUtils.getFieldValue(appContext.getBean("_filterChainProxy"), "stripQueryStringFromUrls"));
assertEquals(true, FieldUtils.getFieldValue(filterList.get(10), "objectDefinitionSource.stripQueryStringFromUrls"));
}
@Test(expected=BeanDefinitionParsingException.class)
public void duplicateElementCausesError() throws Exception {
setContext("<http auto-config='true' /><http auto-config='true' />" + AUTH_PROVIDER_XML);
}
}
private void checkAutoConfigFilters(List filterList) throws Exception {
assertEquals("Expected 11 filters in chain", 11, filterList.size());
Iterator filters = filterList.iterator();
assertTrue(filters.next() instanceof HttpSessionContextIntegrationFilter);
assertTrue(filters.next() instanceof HttpSessionContextIntegrationFilter);
assertTrue(filters.next() instanceof LogoutFilter);
Object authProcFilter = filters.next();
assertTrue(authProcFilter instanceof AuthenticationProcessingFilter);
// Check RememberMeServices has been set on AuthenticationProcessingFilter
// Check RememberMeServices has been set on AuthenticationProcessingFilter
Object rms = FieldUtils.getFieldValue(authProcFilter, "rememberMeServices");
assertNotNull(rms);
assertTrue(rms instanceof RememberMeServices);
@@ -109,7 +111,7 @@ public class HttpSecurityBeanDefinitionParserTests {
assertTrue(filters.next() instanceof RememberMeProcessingFilter);
assertTrue(filters.next() instanceof AnonymousProcessingFilter);
assertTrue(filters.next() instanceof ExceptionTranslationFilter);
assertTrue(filters.next() instanceof SessionFixationProtectionFilter);
assertTrue(filters.next() instanceof SessionFixationProtectionFilter);
Object fsiObj = filters.next();
assertTrue(fsiObj instanceof FilterSecurityInterceptor);
FilterSecurityInterceptor fsi = (FilterSecurityInterceptor) fsiObj;
@@ -138,7 +140,6 @@ public class HttpSecurityBeanDefinitionParserTests {
// This will be matched by the default pattern ".*"
List allFilters = getFilters("/ImCaughtByTheUniversalMatchPattern");
checkAutoConfigFilters(allFilters);
assertEquals(false, FieldUtils.getFieldValue(appContext.getBean("_filterChainProxy"), "stripQueryStringFromUrls"));
assertEquals(false, FieldUtils.getFieldValue(allFilters.get(10), "objectDefinitionSource.stripQueryStringFromUrls"));
}
@@ -152,6 +153,7 @@ public class HttpSecurityBeanDefinitionParserTests {
// These will be matched by the default pattern "/**"
checkAutoConfigFilters(getFilters("/secure"));
checkAutoConfigFilters(getFilters("/ImCaughtByTheUniversalMatchPattern"));
}
@Test
@@ -182,34 +184,34 @@ public class HttpSecurityBeanDefinitionParserTests {
"<http>" +
" <form-login login-page='noLeadingSlash'/>" +
"</http>" + AUTH_PROVIDER_XML);
}
}
@Test(expected=BeanCreationException.class)
public void invalidDefaultTargetUrlIsDetected() throws Exception {
setContext(
"<http>" +
" <form-login default-target-url='noLeadingSlash'/>" +
"</http>" + AUTH_PROVIDER_XML);
}
}
@Test(expected=BeanCreationException.class)
public void invalidLogoutUrlIsDetected() throws Exception {
setContext(
"<http>" +
" <logout logout-url='noLeadingSlash'/>" +
" <logout logout-url='noLeadingSlash'/>" +
" <form-login />" +
"</http>" + AUTH_PROVIDER_XML);
}
}
@Test(expected=BeanCreationException.class)
public void invalidLogoutSuccessUrlIsDetected() throws Exception {
setContext(
"<http>" +
" <logout logout-success-url='noLeadingSlash'/>" +
" <logout logout-success-url='noLeadingSlash'/>" +
" <form-login />" +
"</http>" + AUTH_PROVIDER_XML);
}
}
@Test
public void lowerCaseComparisonIsRespectedBySecurityFilterInvocationDefinitionSource() throws Exception {
setContext(
@@ -251,27 +253,27 @@ public class HttpSecurityBeanDefinitionParserTests {
public void oncePerRequestAttributeIsSupported() throws Exception {
setContext("<http once-per-request='false'><http-basic /></http>" + AUTH_PROVIDER_XML);
List filters = getFilters("/someurl");
FilterSecurityInterceptor fsi = (FilterSecurityInterceptor) filters.get(filters.size() - 1);
assertFalse(fsi.isObserveOncePerRequest());
}
@Test
public void accessDeniedPageAttributeIsSupported() throws Exception {
setContext("<http access-denied-page='/access-denied'><http-basic /></http>" + AUTH_PROVIDER_XML);
List filters = getFilters("/someurl");
ExceptionTranslationFilter etf = (ExceptionTranslationFilter) filters.get(filters.size() - 3);
assertEquals("/access-denied", FieldUtils.getFieldValue(etf, "accessDeniedHandler.errorPage"));
}
@Test(expected=BeanDefinitionStoreException.class)
public void invalidAccessDeniedUrlIsDetected() throws Exception {
setContext("<http auto-config='true' access-denied-page='noLeadingSlash'/>" + AUTH_PROVIDER_XML);
}
}
@Test
public void interceptUrlWithRequiresChannelAddsChannelFilterToStack() throws Exception {
setContext(
@@ -300,24 +302,6 @@ public class HttpSecurityBeanDefinitionParserTests {
assertEquals(Integer.valueOf(9443), pm.lookupHttpsPort(9080));
}
@Test
public void portMappingsWorkWithPlaceholders() throws Exception {
System.setProperty("http", "9080");
System.setProperty("https", "9443");
setContext(
" <b:bean id='configurer' class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'/>" +
" <http auto-config='true'>" +
" <port-mappings>" +
" <port-mapping http='${http}' https='${https}'/>" +
" </port-mappings>" +
" </http>" + AUTH_PROVIDER_XML);
PortMapperImpl pm = (PortMapperImpl) appContext.getBean(BeanIds.PORT_MAPPER);
assertEquals(1, pm.getTranslatedPortMappings().size());
assertEquals(Integer.valueOf(9080), pm.lookupHttpPort(9443));
assertEquals(Integer.valueOf(9443), pm.lookupHttpsPort(9080));
}
@Test
public void externalFiltersAreTreatedCorrectly() throws Exception {
// Decorated user-filters should be added to stack. The others should be ignored.
@@ -328,21 +312,21 @@ public class HttpSecurityBeanDefinitionParserTests {
"</b:bean>" +
"<b:bean id='userFilter1' class='org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter'>" +
" <custom-filter before='SESSION_CONTEXT_INTEGRATION_FILTER'/>" +
"</b:bean>" +
"</b:bean>" +
"<b:bean id='userFilter2' class='org.springframework.security.util.MockFilter'>" +
" <custom-filter position='FIRST'/>" +
"</b:bean>" +
"</b:bean>" +
"<b:bean id='userFilter3' class='org.springframework.security.util.MockFilter'/>" +
"<b:bean id='userFilter4' class='org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter'/>"
);
List filters = getFilters("/someurl");
assertEquals(14, filters.size());
assertTrue(filters.get(0) instanceof MockFilter);
assertTrue(filters.get(0) instanceof MockFilter);
assertTrue(filters.get(1) instanceof SecurityContextHolderAwareRequestFilter);
assertTrue(filters.get(4) instanceof SecurityContextHolderAwareRequestFilter);
}
@Test(expected=BeanCreationException.class)
public void twoFiltersWithSameOrderAreRejected() {
setContext(
@@ -361,7 +345,7 @@ public class HttpSecurityBeanDefinitionParserTests {
"<b:bean id='tokenRepo' " +
"class='org.springframework.security.ui.rememberme.InMemoryTokenRepositoryImpl'/> " + AUTH_PROVIDER_XML);
Object rememberMeServices = appContext.getBean(BeanIds.REMEMBER_ME_SERVICES);
assertTrue(rememberMeServices instanceof PersistentTokenBasedRememberMeServices);
}
@@ -375,11 +359,11 @@ public class HttpSecurityBeanDefinitionParserTests {
" <b:constructor-arg value='tokendb'/>" +
"</b:bean>" + AUTH_PROVIDER_XML);
Object rememberMeServices = appContext.getBean(BeanIds.REMEMBER_ME_SERVICES);
assertTrue(rememberMeServices instanceof PersistentTokenBasedRememberMeServices);
}
}
@Test
public void rememberMeServiceWorksWithExternalServicesImpl() throws Exception {
setContext(
@@ -392,13 +376,9 @@ public class HttpSecurityBeanDefinitionParserTests {
" <b:property name='tokenValiditySeconds' value='5000'/>" +
"</b:bean>" +
AUTH_PROVIDER_XML);
assertEquals(5000, FieldUtils.getFieldValue(appContext.getBean(BeanIds.REMEMBER_ME_SERVICES),
"tokenValiditySeconds"));
// SEC-909
LogoutHandler[] logoutHandlers = (LogoutHandler[]) FieldUtils.getFieldValue(appContext.getBean(BeanIds.LOGOUT_FILTER), "handlers");
assertEquals(2, logoutHandlers.length);
assertEquals(appContext.getBean(BeanIds.REMEMBER_ME_SERVICES), logoutHandlers[1]);
assertEquals(5000, FieldUtils.getFieldValue(appContext.getBean(BeanIds.REMEMBER_ME_SERVICES),
"tokenValiditySeconds"));
}
@Test
@@ -407,10 +387,10 @@ public class HttpSecurityBeanDefinitionParserTests {
"<http auto-config='true'>" +
" <remember-me key='ourkey' token-validity-seconds='10000' />" +
"</http>" + AUTH_PROVIDER_XML);
assertEquals(10000, FieldUtils.getFieldValue(appContext.getBean(BeanIds.REMEMBER_ME_SERVICES),
"tokenValiditySeconds"));
}
assertEquals(10000, FieldUtils.getFieldValue(appContext.getBean(BeanIds.REMEMBER_ME_SERVICES),
"tokenValiditySeconds"));
}
@Test
public void rememberMeServiceConfigurationParsesWithCustomUserService() {
setContext(
@@ -420,8 +400,8 @@ public class HttpSecurityBeanDefinitionParserTests {
"<b:bean id='userService' class='org.springframework.security.userdetails.MockUserDetailsService'/> " +
AUTH_PROVIDER_XML);
// AbstractRememberMeServices rememberMeServices = (AbstractRememberMeServices) appContext.getBean(BeanIds.REMEMBER_ME_SERVICES);
}
}
@Test
public void x509SupportAddsFilterAtExpectedPosition() throws Exception {
setContext(
@@ -440,11 +420,11 @@ public class HttpSecurityBeanDefinitionParserTests {
" <concurrent-session-control session-registry-alias='seshRegistry' expired-url='/expired'/>" +
"</http>" + AUTH_PROVIDER_XML);
List filters = getFilters("/someurl");
assertTrue(filters.get(0) instanceof ConcurrentSessionFilter);
assertTrue(filters.get(0) instanceof ConcurrentSessionFilter);
assertNotNull(appContext.getBean("seshRegistry"));
assertNotNull(appContext.getBean(BeanIds.CONCURRENT_SESSION_CONTROLLER));
}
}
@Test
public void externalSessionRegistryBeanIsConfiguredCorrectly() throws Exception {
@@ -456,12 +436,12 @@ public class HttpSecurityBeanDefinitionParserTests {
AUTH_PROVIDER_XML);
Object sessionRegistry = appContext.getBean("seshRegistry");
Object sessionRegistryFromFilter = FieldUtils.getFieldValue(
appContext.getBean(BeanIds.CONCURRENT_SESSION_FILTER),"sessionRegistry");
appContext.getBean(BeanIds.CONCURRENT_SESSION_FILTER),"sessionRegistry");
Object sessionRegistryFromController = FieldUtils.getFieldValue(
appContext.getBean(BeanIds.CONCURRENT_SESSION_CONTROLLER),"sessionRegistry");
appContext.getBean(BeanIds.CONCURRENT_SESSION_CONTROLLER),"sessionRegistry");
Object sessionRegistryFromFixationFilter = FieldUtils.getFieldValue(
appContext.getBean(BeanIds.SESSION_FIXATION_PROTECTION_FILTER),"sessionRegistry");
appContext.getBean(BeanIds.SESSION_FIXATION_PROTECTION_FILTER),"sessionRegistry");
assertSame(sessionRegistry, sessionRegistryFromFilter);
assertSame(sessionRegistry, sessionRegistryFromController);
assertSame(sessionRegistry, sessionRegistryFromFixationFilter);
@@ -493,8 +473,8 @@ public class HttpSecurityBeanDefinitionParserTests {
" </b:property>" +
"</b:bean>" +
"<authentication-manager alias='authManager' session-controller-ref='sc'/>" + AUTH_PROVIDER_XML);
}
}
@Test(expected=ConcurrentLoginException.class)
public void concurrentSessionMaxSessionsIsCorrectlyConfigured() throws Exception {
setContext(
@@ -508,16 +488,16 @@ public class HttpSecurityBeanDefinitionParserTests {
req.setSession(new MockHttpSession());
auth.setDetails(new WebAuthenticationDetails(req));
try {
seshController.checkAuthenticationAllowed(auth);
seshController.checkAuthenticationAllowed(auth);
} catch (ConcurrentLoginException e) {
fail("First login should be allowed");
}
fail("First login should be allowed");
}
seshController.registerSuccessfulAuthentication(auth);
req.setSession(new MockHttpSession());
try {
seshController.checkAuthenticationAllowed(auth);
seshController.checkAuthenticationAllowed(auth);
} catch (ConcurrentLoginException e) {
fail("Second login should be allowed");
fail("Second login should be allowed");
}
auth.setDetails(new WebAuthenticationDetails(req));
seshController.registerSuccessfulAuthentication(auth);
@@ -534,10 +514,10 @@ public class HttpSecurityBeanDefinitionParserTests {
" <b:constructor-arg value='/customlogin'/>" +
"</b:bean>" + AUTH_PROVIDER_XML);
ExceptionTranslationFilter etf = (ExceptionTranslationFilter) getFilters("/someurl").get(8);
assertTrue("ExceptionTranslationFilter should be configured with custom entry point",
assertTrue("ExceptionTranslationFilter should be configured with custom entry point",
etf.getAuthenticationEntryPoint() instanceof MockAuthenticationEntryPoint);
}
@Test
/** SEC-742 */
public void rememberMeServicesWorksWithoutBasicProcessingFilter() {
@@ -558,7 +538,7 @@ public class HttpSecurityBeanDefinitionParserTests {
assertFalse(filters.get(1) instanceof SessionFixationProtectionFilter);
}
/**
* See SEC-750. If the http security post processor causes beans to be instantiated too eagerly, they way miss
* additional processing. In this method we have a UserDetailsService which is referenced from the namespace
@@ -577,18 +557,18 @@ public class HttpSecurityBeanDefinitionParserTests {
assertEquals("Hello from the post processor!", service.getPostProcessorWasHere());
}
/**
* SEC-795. Two methods that exercise the scenarios that will or won't result in a protected login page warning.
* Check the log.
*/
@Test
public void unprotectedLoginPageDoesntResultInWarning() {
// Anonymous access configured
// Anonymous access configured
setContext(
" <http>" +
" <intercept-url pattern='/login.jsp*' access='IS_AUTHENTICATED_ANONYMOUSLY'/>" +
" <intercept-url pattern='/**' access='ROLE_A'/>" +
" <intercept-url pattern='/**' access='ROLE_A'/>" +
" <anonymous />" +
" <form-login login-page='/login.jsp' default-target-url='/messageList.html'/>" +
" </http>" + AUTH_PROVIDER_XML);
@@ -600,9 +580,9 @@ public class HttpSecurityBeanDefinitionParserTests {
" <intercept-url pattern='/**' access='ROLE_A'/>" +
" <anonymous />" +
" <form-login login-page='/login.jsp' default-target-url='/messageList.html'/>" +
" </http>" + AUTH_PROVIDER_XML);
" </http>" + AUTH_PROVIDER_XML);
}
@Test
public void protectedLoginPageResultsInWarning() {
// Protected, no anonymous filter configured.
@@ -623,34 +603,20 @@ public class HttpSecurityBeanDefinitionParserTests {
@Test
public void settingCreateSessionToAlwaysSetsFilterPropertiesCorrectly() throws Exception {
// Protected, no anonymous filter configured.
setContext("<http auto-config='true' create-session='always'/>" + AUTH_PROVIDER_XML);
assertEquals(Boolean.TRUE, FieldUtils.getFieldValue(appContext.getBean(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER), "forceEagerSessionCreation"));
assertEquals(Boolean.TRUE, FieldUtils.getFieldValue(appContext.getBean(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER), "allowSessionCreation"));
}
assertEquals(Boolean.TRUE, FieldUtils.getFieldValue(appContext.getBean(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER), "allowSessionCreation"));
}
@Test
public void settingCreateSessionToNeverSetsFilterPropertiesCorrectly() throws Exception {
// Protected, no anonymous filter configured.
setContext("<http auto-config='true' create-session='never'/>" + AUTH_PROVIDER_XML);
assertEquals(Boolean.FALSE, FieldUtils.getFieldValue(appContext.getBean(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER), "forceEagerSessionCreation"));
assertEquals(Boolean.FALSE, FieldUtils.getFieldValue(appContext.getBean(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER), "allowSessionCreation"));
}
/* SEC-934 */
@Test
public void supportsTwoIdenticalInterceptUrls() {
setContext(
"<http auto-config='true'>" +
" <intercept-url pattern='/someurl' access='ROLE_A'/>" +
" <intercept-url pattern='/someurl' access='ROLE_B'/>" +
"</http>" + AUTH_PROVIDER_XML);
FilterSecurityInterceptor fis = (FilterSecurityInterceptor) appContext.getBean(BeanIds.FILTER_SECURITY_INTERCEPTOR);
FilterInvocationDefinitionSource fids = fis.getObjectDefinitionSource();
ConfigAttributeDefinition attrDef = fids.getAttributes(createFilterinvocation("/someurl", null));
assertEquals(1, attrDef.getConfigAttributes().size());
assertTrue(attrDef.contains(new SecurityConfig("ROLE_B")));
}
assertEquals(Boolean.FALSE, FieldUtils.getFieldValue(appContext.getBean(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER), "allowSessionCreation"));
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
@@ -1,6 +1,8 @@
package org.springframework.security.config;
import static org.junit.Assert.*;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Test;
@@ -11,7 +13,6 @@ import org.springframework.security.providers.dao.DaoAuthenticationProvider;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.jdbc.JdbcUserDetailsManager;
import org.springframework.security.util.AuthorityUtils;
import org.springframework.security.util.FieldUtils;
import org.springframework.security.util.InMemoryXmlApplicationContext;
/**
@@ -50,37 +51,24 @@ public class JdbcUserServiceBeanDefinitionParserTests {
@Test
public void beanIdIsParsedCorrectly() {
setContext("<jdbc-user-service id='myUserService' data-source-ref='dataSource'/>" + DATA_SOURCE);
assertTrue(appContext.getBean("myUserService") instanceof JdbcUserDetailsManager);
JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean("myUserService");
}
@Test
public void usernameAndAuthorityQueriesAreParsedCorrectly() throws Exception {
String userQuery = "select username, password, true from users where username = ?";
String authoritiesQuery = "select username, authority from authorities where username = ? and 1 = 1";
public void usernameAndGroupQueriesAreParsedCorrectly() {
setContext("<jdbc-user-service id='myUserService' " +
"data-source-ref='dataSource' " +
"users-by-username-query='"+ userQuery +"' " +
"authorities-by-username-query='" + authoritiesQuery + "'/>" + DATA_SOURCE);
"users-by-username-query='select username,password,enabled from users where username = ?' " +
"authorities-by-username-query='select username,authority from authorities where username = ?'/>" + DATA_SOURCE);
JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean("myUserService");
assertEquals(userQuery, FieldUtils.getFieldValue(mgr, "usersByUsernameQuery"));
assertEquals(authoritiesQuery, FieldUtils.getFieldValue(mgr, "authoritiesByUsernameQuery"));
assertTrue(mgr.loadUserByUsername("rod") != null);
}
@Test
public void groupQueryIsParsedCorrectly() throws Exception {
setContext("<jdbc-user-service id='myUserService' " +
"data-source-ref='dataSource' " +
"group-authorities-by-username-query='blah blah'/>" + DATA_SOURCE);
JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean("myUserService");
assertEquals("blah blah", FieldUtils.getFieldValue(mgr, "groupAuthoritiesByUsernameQuery"));
assertTrue((Boolean)FieldUtils.getFieldValue(mgr, "enableGroups"));
}
@Test
public void cacheRefIsparsedCorrectly() {
setContext("<jdbc-user-service id='myUserService' cache-ref='userCache' data-source-ref='dataSource'/>"
+ DATA_SOURCE +USER_CACHE_XML);
JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean("myUserService");
CachingUserDetailsService cachingUserService =
(CachingUserDetailsService) appContext.getBean("myUserService" + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX);
assertSame(cachingUserService.getUserCache(), appContext.getBean("userCache"));
@@ -12,13 +12,12 @@ import org.springframework.security.util.FieldUtils;
import org.springframework.security.util.InMemoryXmlApplicationContext;
/**
*
*
* @author Luke Taylor
* $Id$
*/
public class SessionRegistryInjectionBeanPostProcessorTests {
private AbstractXmlApplicationContext appContext;
@After
public void closeAppContext() {
if (appContext != null) {
@@ -37,31 +36,31 @@ public class SessionRegistryInjectionBeanPostProcessorTests {
"<http auto-config='true'/>" +
"<b:bean id='sc' class='org.springframework.security.concurrent.ConcurrentSessionControllerImpl'>" +
" <b:property name='sessionRegistry'>" +
" <b:bean class='org.springframework.security.concurrent.SessionRegistryImpl'/>" +
" <b:bean class='org.springframework.security.concurrent.SessionRegistryImpl'/>" +
" </b:property>" +
"</b:bean>" +
"<authentication-manager alias='authManager' session-controller-ref='sc'/>" +
ConfigTestUtils.AUTH_PROVIDER_XML);
assertNotNull(FieldUtils.getFieldValue(appContext.getBean(BeanIds.SESSION_FIXATION_PROTECTION_FILTER), "sessionRegistry"));
assertNotNull(FieldUtils.getFieldValue(appContext.getBean(BeanIds.FORM_LOGIN_FILTER), "sessionRegistry"));
"<authentication-manager alias='authManager' session-controller-ref='sc'/>" +
HttpSecurityBeanDefinitionParserTests.AUTH_PROVIDER_XML);
assertNotNull(FieldUtils.getFieldValue(appContext.getBean(BeanIds.SESSION_FIXATION_PROTECTION_FILTER), "sessionRegistry"));
assertNotNull(FieldUtils.getFieldValue(appContext.getBean(BeanIds.FORM_LOGIN_FILTER), "sessionRegistry"));
}
@Test
public void sessionRegistryIsSetOnFiltersWhenUsingCustomControllerWithNonStandardController() throws Exception {
setContext(
"<http auto-config='true'/>" +
"<b:bean id='sc' class='org.springframework.security.config.SessionRegistryInjectionBeanPostProcessorTests$MockConcurrentSessionController'/>" +
"<b:bean id='sessionRegistry' class='org.springframework.security.concurrent.SessionRegistryImpl'/>" +
"<authentication-manager alias='authManager' session-controller-ref='sc'/>" +
ConfigTestUtils.AUTH_PROVIDER_XML);
assertNotNull(FieldUtils.getFieldValue(appContext.getBean(BeanIds.SESSION_FIXATION_PROTECTION_FILTER), "sessionRegistry"));
assertNotNull(FieldUtils.getFieldValue(appContext.getBean(BeanIds.FORM_LOGIN_FILTER), "sessionRegistry"));
"<authentication-manager alias='authManager' session-controller-ref='sc'/>" +
HttpSecurityBeanDefinitionParserTests.AUTH_PROVIDER_XML);
assertNotNull(FieldUtils.getFieldValue(appContext.getBean(BeanIds.SESSION_FIXATION_PROTECTION_FILTER), "sessionRegistry"));
assertNotNull(FieldUtils.getFieldValue(appContext.getBean(BeanIds.FORM_LOGIN_FILTER), "sessionRegistry"));
}
public static class MockConcurrentSessionController implements ConcurrentSessionController {
public void checkAuthenticationAllowed(Authentication request) throws AuthenticationException {
}
public void registerSuccessfulAuthentication(Authentication authentication) {
}
public void checkAuthenticationAllowed(Authentication request) throws AuthenticationException {
}
public void registerSuccessfulAuthentication(Authentication authentication) {
}
}
}
@@ -15,10 +15,14 @@
package org.springframework.security.context;
import junit.framework.ComparisonFailure;
import junit.framework.TestCase;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import java.util.Random;
/**
* Tests {@link SecurityContextHolder}.
*
@@ -26,13 +30,193 @@ import org.springframework.security.providers.UsernamePasswordAuthenticationToke
* @version $Id$
*/
public class SecurityContextHolderTests extends TestCase {
//~ Static fields/initializers =====================================================================================
private static int errors = 0;
private static final int NUM_OPS = 5;
private static final int NUM_THREADS = 5;
//~ Constructors ===================================================================================================
public SecurityContextHolderTests() {
super();
}
public SecurityContextHolderTests(String arg0) {
super(arg0);
}
//~ Methods ========================================================================================================
private void loadStartAndWaitForThreads(boolean topLevelThread, String prefix, int createThreads,
boolean expectAllThreadsToUseIdenticalAuthentication, boolean expectChildrenToShareAuthenticationWithParent) {
Thread[] threads = new Thread[createThreads];
errors = 0;
if (topLevelThread) {
// PARENT (TOP-LEVEL) THREAD CREATION
if (expectChildrenToShareAuthenticationWithParent) {
// An InheritableThreadLocal
for (int i = 0; i < threads.length; i++) {
if ((i % 2) == 0) {
// Don't inject auth into current thread; neither current thread or child will have authentication
threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, false, true, null);
} else {
// Inject auth into current thread, but not child; current thread will have auth, child will also have auth
threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, false, true,
prefix + "Auth_Parent_" + i);
}
}
} else if (expectAllThreadsToUseIdenticalAuthentication) {
// A global
SecurityContextHolder.getContext()
.setAuthentication(new UsernamePasswordAuthenticationToken("GLOBAL_USERNAME",
"pass"));
for (int i = 0; i < threads.length; i++) {
if ((i % 2) == 0) {
// Don't inject auth into current thread;both current thread and child will have same authentication
threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, true, true,
"GLOBAL_USERNAME");
} else {
// Inject auth into current thread; current thread will have auth, child will also have auth
threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, true, true, "GLOBAL_USERNAME");
}
}
} else {
// A standard ThreadLocal
for (int i = 0; i < threads.length; i++) {
if ((i % 2) == 0) {
// Don't inject auth into current thread; neither current thread or child will have authentication
threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, false, false, null);
} else {
// Inject auth into current thread, but not child; current thread will have auth, child will not have auth
threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, false, false,
prefix + "Auth_Parent_" + i);
}
}
}
} else {
// CHILD THREAD CREATION
if (expectChildrenToShareAuthenticationWithParent || expectAllThreadsToUseIdenticalAuthentication) {
// The children being created are all expected to have security (ie an InheritableThreadLocal/global AND auth was injected into parent)
for (int i = 0; i < threads.length; i++) {
String expectedUsername = prefix;
if (expectAllThreadsToUseIdenticalAuthentication) {
expectedUsername = "GLOBAL_USERNAME";
}
// Don't inject auth into current thread; the current thread will obtain auth from its parent
// NB: As topLevelThread = true, no further child threads will be created
threads[i] = makeThread(prefix + "->child->Inherited_Auth_Child_" + i, false, false,
expectAllThreadsToUseIdenticalAuthentication, false, expectedUsername);
}
} else {
// The children being created are NOT expected to have security (ie not an InheritableThreadLocal OR auth was not injected into parent)
for (int i = 0; i < threads.length; i++) {
// Don't inject auth into current thread; neither current thread or child will have authentication
// NB: As topLevelThread = true, no further child threads will be created
threads[i] = makeThread(prefix + "->child->Unauth_Child_" + i, false, false, false, false, null);
}
}
}
// Start and execute the threads
startAndRun(threads);
}
public static void main(String[] args) {
junit.textui.TestRunner.run(SecurityContextHolderTests.class);
}
private Thread makeThread(final String threadIdentifier, final boolean topLevelThread,
final boolean injectAuthIntoCurrentThread, final boolean expectAllThreadsToUseIdenticalAuthentication,
final boolean expectChildrenToShareAuthenticationWithParent, final String expectedUsername) {
final Random rnd = new Random();
Thread t = new Thread(new Runnable() {
public void run() {
if (injectAuthIntoCurrentThread) {
// Set authentication in this thread
SecurityContextHolder.getContext()
.setAuthentication(new UsernamePasswordAuthenticationToken(
expectedUsername, "pass"));
//System.out.println(threadIdentifier + " - set to " + SecurityContextHolder.getContext().getAuthentication());
} else {
//System.out.println(threadIdentifier + " - not set (currently " + SecurityContextHolder.getContext().getAuthentication() + ")");
}
// Do some operations in current thread, checking authentication is as expected in the current thread (ie another thread doesn't change it)
for (int i = 0; i < NUM_OPS; i++) {
String currentUsername = (SecurityContextHolder.getContext().getAuthentication() == null)
? null : SecurityContextHolder.getContext().getAuthentication().getName();
if ((i % 7) == 0) {
System.out.println(threadIdentifier + " at " + i + " username " + currentUsername);
}
try {
TestCase.assertEquals("Failed on iteration " + i + "; Authentication was '"
+ currentUsername + "' but principal was expected to contain username '"
+ expectedUsername + "'", expectedUsername, currentUsername);
} catch (ComparisonFailure err) {
errors++;
throw err;
}
try {
Thread.sleep(rnd.nextInt(250));
} catch (InterruptedException ignore) {}
}
// Load some children threads, checking the authentication is as expected in the children (ie another thread doesn't change it)
if (topLevelThread) {
// Make four children, but we don't want the children to have any more children (so anti-nature, huh?)
if (injectAuthIntoCurrentThread && expectChildrenToShareAuthenticationWithParent) {
loadStartAndWaitForThreads(false, threadIdentifier, 4,
expectAllThreadsToUseIdenticalAuthentication, true);
} else {
loadStartAndWaitForThreads(false, threadIdentifier, 4,
expectAllThreadsToUseIdenticalAuthentication, false);
}
}
}
}, threadIdentifier);
return t;
}
public final void setUp() throws Exception {
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
}
private void startAndRun(Thread[] threads) {
// Start them up
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
// Wait for them to finish
while (stillRunning(threads)) {
try {
Thread.sleep(250);
} catch (InterruptedException ignore) {}
}
}
private boolean stillRunning(Thread[] threads) {
for (int i = 0; i < threads.length; i++) {
if (threads[i].isAlive()) {
return true;
}
}
return false;
}
public void testContextHolderGetterSetterClearer() {
SecurityContext sc = new SecurityContextImpl();
sc.setAuthentication(new UsernamePasswordAuthenticationToken("Foobar", "pass"));
@@ -56,4 +240,34 @@ public class SecurityContextHolderTests extends TestCase {
assertTrue(true);
}
}
public void testSynchronizationCustomStrategyLoading() {
SecurityContextHolder.setStrategyName(InheritableThreadLocalSecurityContextHolderStrategy.class.getName());
assertTrue(new SecurityContextHolder().toString()
.lastIndexOf("SecurityContextHolder[strategy='org.springframework.security.context.InheritableThreadLocalSecurityContextHolderStrategy'") != -1);
loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, true);
assertEquals("Thread errors detected; review log output for details", 0, errors);
}
public void testSynchronizationGlobal() throws Exception {
SecurityContextHolder.clearContext();
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_GLOBAL);
loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, true, false);
assertEquals("Thread errors detected; review log output for details", 0, errors);
}
public void testSynchronizationInheritableThreadLocal()
throws Exception {
SecurityContextHolder.clearContext();
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, true);
assertEquals("Thread errors detected; review log output for details", 0, errors);
}
public void testSynchronizationThreadLocal() throws Exception {
SecurityContextHolder.clearContext();
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_THREADLOCAL);
loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, false);
assertEquals("Thread errors detected; review log output for details", 0, errors);
}
}
@@ -1,54 +0,0 @@
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) {
}
}
}
@@ -36,7 +36,7 @@ import org.springframework.security.RunAsManager;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.intercept.method.MethodDefinitionSource;
import org.springframework.security.intercept.method.AbstractMethodDefinitionSource;
import org.springframework.security.intercept.method.MockMethodDefinitionSource;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
@@ -446,26 +446,26 @@ public class MethodSecurityInterceptorTests extends TestCase {
}
}
private class MockObjectDefinitionSourceWhichOnlySupportsStrings implements MethodDefinitionSource {
private class MockObjectDefinitionSourceWhichOnlySupportsStrings extends AbstractMethodDefinitionSource {
public Collection getConfigAttributeDefinitions() {
return null;
}
public ConfigAttributeDefinition getAttributes(Method method, Class targetClass) {
protected ConfigAttributeDefinition lookupAttributes(Method method) {
throw new UnsupportedOperationException("mock method not implemented");
}
public boolean supports(Class clazz) {
public ConfigAttributeDefinition getAttributes(Method method, Class targetClass) {
throw new UnsupportedOperationException("mock method not implemented");
}
public boolean supports(Class clazz) {
if (String.class.isAssignableFrom(clazz)) {
return true;
} else {
return false;
}
}
public ConfigAttributeDefinition getAttributes(Object object) {
throw new UnsupportedOperationException("mock method not implemented");
}
}
private class MockRunAsManagerWhichOnlySupportsStrings implements RunAsManager {
@@ -12,10 +12,4 @@ public class DefaultSpringSecurityContextSourceTests {
public void instantiationSucceeds() {
new DefaultSpringSecurityContextSource("ldap://blah:789/dc=springframework,dc=org");
}
@Test
public void supportsSpacesInUrl() {
new DefaultSpringSecurityContextSource("ldap://myhost:10389/dc=spring%20framework,dc=org");
}
}
@@ -44,7 +44,8 @@ public class SpringSecurityAuthenticationSourceTests {
@Test(expected=IllegalArgumentException.class)
public void getPrincipalRejectsNonLdapUserDetailsObject() {
AuthenticationSource source = new SpringSecurityAuthenticationSource();
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken(new Object(), "password"));
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken(new Object(), "password", null));
source.getPrincipal();
}
@@ -52,7 +53,8 @@ public class SpringSecurityAuthenticationSourceTests {
@Test
public void expectedCredentialsAreReturned() {
AuthenticationSource source = new SpringSecurityAuthenticationSource();
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken(new Object(), "password"));
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken(new Object(), "password", null));
assertEquals("password", source.getCredentials());
}
@@ -64,7 +66,7 @@ public class SpringSecurityAuthenticationSourceTests {
user.setDn(new DistinguishedName("uid=joe,ou=users"));
AuthenticationSource source = new SpringSecurityAuthenticationSource();
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken(user.createUserDetails(), null));
new TestingAuthenticationToken(user.createUserDetails(), null, null));
assertEquals("uid=joe, ou=users", source.getPrincipal());
}
@@ -56,17 +56,6 @@ public class FilterBasedLdapUserSearchTests extends AbstractLdapIntegrationTests
assertEquals(new DistinguishedName("uid=bob,ou=people"), bob.getDn());
}
@Test
public void searchForNameWithCommaSucceeds() {
FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", "(uid={0})", dirCtxFactory);
locator.setSearchSubtree(false);
DirContextOperations jerry = locator.searchForUser("jerry");
assertEquals("jerry", jerry.getStringAttribute("uid"));
assertEquals(new DistinguishedName("cn=mouse\\, jerry,ou=people"), jerry.getDn());
}
// Try some funny business with filters.
@Test
public void extraFilterPartToExcludeBob() throws Exception {
@@ -119,11 +119,10 @@ public class ProviderManagerTests {
}
@Test(expected=IllegalArgumentException.class)
public void getProvidersFailsIfProviderListNotSet() throws Exception {
public void startupFailsIfProviderListNotSet() throws Exception {
ProviderManager mgr = new ProviderManager();
mgr.afterPropertiesSet();
mgr.getProviders();
}
@Test(expected=IllegalArgumentException.class)
@@ -0,0 +1,77 @@
/* 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.providers;
import junit.framework.TestCase;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
/**
* Tests {@link TestingAuthenticationToken}.
*
* @author Ben Alex
* @version $Id$
*/
public class TestingAuthenticationTokenTests extends TestCase {
//~ Constructors ===================================================================================================
public TestingAuthenticationTokenTests() {
super();
}
public TestingAuthenticationTokenTests(String arg0) {
super(arg0);
}
//~ Methods ========================================================================================================
public static void main(String[] args) {
junit.textui.TestRunner.run(TestingAuthenticationTokenTests.class);
}
public final void setUp() throws Exception {
super.setUp();
}
public void testAuthenticated() {
TestingAuthenticationToken token = new TestingAuthenticationToken("Test", "Password", null);
assertTrue(!token.isAuthenticated());
token.setAuthenticated(true);
assertTrue(token.isAuthenticated());
}
public void testGetters() {
TestingAuthenticationToken token = new TestingAuthenticationToken("Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")});
assertEquals("Test", token.getPrincipal());
assertEquals("Password", token.getCredentials());
assertEquals("ROLE_ONE", token.getAuthorities()[0].getAuthority());
assertEquals("ROLE_TWO", token.getAuthorities()[1].getAuthority());
}
public void testNoArgConstructorDoesntExist() {
Class clazz = TestingAuthenticationToken.class;
try {
clazz.getDeclaredConstructor((Class[]) null);
fail("Should have thrown NoSuchMethodException");
} catch (NoSuchMethodException expected) {
assertTrue(true);
}
}
}
@@ -25,7 +25,6 @@ import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.MockAuthenticationManager;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.ui.rememberme.NullRememberMeServices;
import org.springframework.security.ui.rememberme.TokenBasedRememberMeServices;
import org.springframework.security.ui.savedrequest.SavedRequest;
import org.springframework.security.util.PortResolverImpl;
@@ -77,7 +76,8 @@ public class AbstractProcessingFilterTests extends TestCase {
}
private void executeFilterInContainerSimulator(FilterConfig filterConfig, Filter filter, ServletRequest request,
ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
filter.init(filterConfig);
filter.doFilter(request, response, filterChain);
filter.destroy();
@@ -115,7 +115,7 @@ public class AbstractProcessingFilterTests extends TestCase {
SecurityContextHolder.clearContext();
}
public void testDefaultProcessesFilterUrlMatchesWithPathParameter() {
public void testDefaultProcessesFilterUrlWithPathParameter() {
MockHttpServletRequest request = createMockRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter();
@@ -125,6 +125,28 @@ public class AbstractProcessingFilterTests extends TestCase {
assertTrue(filter.requiresAuthentication(request, response));
}
public void testDoFilterWithNonHttpServletRequestDetected() throws Exception {
AbstractProcessingFilter filter = new MockAbstractProcessingFilter();
try {
filter.doFilter(null, new MockHttpServletResponse(), new MockFilterChain());
fail("Should have thrown ServletException");
} catch (ServletException expected) {
assertEquals("Can only process HttpServletRequest", expected.getMessage());
}
}
public void testDoFilterWithNonHttpServletResponseDetected() throws Exception {
AbstractProcessingFilter filter = new MockAbstractProcessingFilter();
try {
filter.doFilter(new MockHttpServletRequest(null, null), null, new MockFilterChain());
fail("Should have thrown ServletException");
} catch (ServletException expected) {
assertEquals("Can only process HttpServletResponse", expected.getMessage());
}
}
public void testFailedAuthenticationRedirectsAppropriately() throws Exception {
// Setup our HTTP request
MockHttpServletRequest request = createMockRequest();
@@ -187,20 +209,25 @@ public class AbstractProcessingFilterTests extends TestCase {
assertEquals("test", SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString());
}
public void testGettersSetters() throws Exception {
public void testGettersSetters() {
AbstractProcessingFilter filter = new MockAbstractProcessingFilter();
filter.setAuthenticationManager(new MockAuthenticationManager());
filter.setDefaultTargetUrl("/default");
filter.setFilterProcessesUrl("/p");
filter.setAuthenticationFailureUrl("/fail");
filter.afterPropertiesSet();
assertNotNull(filter.getRememberMeServices());
filter.setRememberMeServices(new TokenBasedRememberMeServices());
assertEquals(TokenBasedRememberMeServices.class, filter.getRememberMeServices().getClass());
filter.setAuthenticationFailureUrl("/x");
assertEquals("/x", filter.getAuthenticationFailureUrl());
filter.setAuthenticationManager(new MockAuthenticationManager());
assertTrue(filter.getAuthenticationManager() != null);
filter.setDefaultTargetUrl("/default");
assertEquals("/default", filter.getDefaultTargetUrl());
filter.setFilterProcessesUrl("/p");
assertEquals("/p", filter.getFilterProcessesUrl());
filter.setAuthenticationFailureUrl("/fail");
assertEquals("/fail", filter.getAuthenticationFailureUrl());
}
@@ -575,13 +602,11 @@ public class AbstractProcessingFilterTests extends TestCase {
private boolean grantAccess;
public MockAbstractProcessingFilter(boolean grantAccess) {
setRememberMeServices(new NullRememberMeServices());
this.grantAccess = grantAccess;
this.exceptionToThrow = new BadCredentialsException("Mock requested to do so");
}
public MockAbstractProcessingFilter(AuthenticationException exceptionToThrow) {
setRememberMeServices(new NullRememberMeServices());
this.grantAccess = false;
this.exceptionToThrow = exceptionToThrow;
}
@@ -589,7 +614,8 @@ public class AbstractProcessingFilterTests extends TestCase {
private MockAbstractProcessingFilter() {
}
public Authentication attemptAuthentication(HttpServletRequest request) throws AuthenticationException {
public Authentication attemptAuthentication(HttpServletRequest request)
throws AuthenticationException {
if (grantAccess) {
return new UsernamePasswordAuthenticationToken("test", "test",
new GrantedAuthority[] {new GrantedAuthorityImpl("TEST")});
@@ -618,7 +644,11 @@ public class AbstractProcessingFilterTests extends TestCase {
this.expectToProceed = expectToProceed;
}
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
private MockFilterChain() {
}
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
if (expectToProceed) {
assertTrue(true);
} else {
@@ -74,6 +74,6 @@ public class SessionFixationProtectionFilterTests {
}
private void authenticateUser() {
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass"));
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass", null));
}
}
@@ -1,55 +0,0 @@
package org.springframework.security.ui.preauth;
import static org.junit.Assert.*;
import javax.servlet.http.HttpServletRequest;
import org.junit.Before;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.BadCredentialsException;
import org.springframework.security.MockAuthenticationManager;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.util.MockFilterChain;
public class AbstractPreAuthenticatedProcessingFilterTests {
private AbstractPreAuthenticatedProcessingFilter filter;
@Before
public void createFilter() {
filter = new AbstractPreAuthenticatedProcessingFilter() {
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
return "n/a";
}
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
return "doesntmatter";
}
public int getOrder() {
return 0;
}
};
SecurityContextHolder.getContext().setAuthentication(null);
}
@Test
public void filterChainProceedsOnFailedAuthenticationByDefault() throws Exception {
filter.setAuthenticationManager(new MockAuthenticationManager(false));
filter.afterPropertiesSet();
filter.doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(), new MockFilterChain(true));
assertNull(SecurityContextHolder.getContext().getAuthentication());
}
/* SEC-881 */
@Test(expected=BadCredentialsException.class)
public void exceptionIsThrownOnFailedAuthenticationIfContinueFilterChainOnUnsuccessfulAuthenticationSetToFalse() throws Exception {
filter.setContinueFilterChainOnUnsuccessfulAuthentication(false);
filter.setAuthenticationManager(new MockAuthenticationManager(false));
filter.afterPropertiesSet();
filter.doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(), new MockFilterChain(false));
assertNull(SecurityContextHolder.getContext().getAuthentication());
}
}
@@ -160,7 +160,7 @@ public class RememberMeProcessingFilterTests extends TestCase {
public void testOnunsuccessfulLoginIsCalledWhenProviderRejectsAuth() throws Exception {
Authentication remembered = new TestingAuthenticationToken("remembered", "password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_REMEMBERED")});
final Authentication failedAuth = new TestingAuthenticationToken("failed", "");
final Authentication failedAuth = new TestingAuthenticationToken("failed", "", null);
RememberMeProcessingFilter filter = new RememberMeProcessingFilter() {
protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) {
@@ -343,7 +343,7 @@ public class TokenBasedRememberMeServicesTests extends TestCase {
public void testLoginSuccessNormalWithNonUserDetailsBasedPrincipal() {
TokenBasedRememberMeServices services = new TokenBasedRememberMeServices();
// SEC-822
services.setTokenValiditySeconds(500000000);
services.setTokenValiditySeconds(5000000);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("d");
request.addParameter(TokenBasedRememberMeServices.DEFAULT_PARAMETER, "true");
@@ -354,10 +354,6 @@ public class TokenBasedRememberMeServicesTests extends TestCase {
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")}));
Cookie cookie = response.getCookie(TokenBasedRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY);
String expiryTime = services.decodeCookie(cookie.getValue())[1];
long expectedExpiryTime = 1000L * 500000000;
expectedExpiryTime += System.currentTimeMillis();
assertTrue(Long.parseLong(expiryTime) > expectedExpiryTime - 10000);
assertNotNull(cookie);
assertEquals(services.getTokenValiditySeconds(), cookie.getMaxAge());
assertTrue(Base64.isArrayByteBase64(cookie.getValue().getBytes()));
@@ -15,18 +15,8 @@
package org.springframework.security.ui.switchuser;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import junit.framework.TestCase;
import java.util.ArrayList;
import java.util.List;
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.AccountExpiredException;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
@@ -34,34 +24,48 @@ import org.springframework.security.CredentialsExpiredException;
import org.springframework.security.DisabledException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.userdetails.User;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.security.util.FieldUtils;
import org.springframework.security.util.MockFilterChain;
import org.springframework.dao.DataAccessException;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import java.util.List;
import java.util.ArrayList;
/**
* Tests {@link org.springframework.security.ui.switchuser.SwitchUserProcessingFilter}.
*
* @author Mark St.Godard
* @author Luke Taylor
* @version $Id$
*/
public class SwitchUserProcessingFilterTests {
public class SwitchUserProcessingFilterTests extends TestCase {
//~ Constructors ===================================================================================================
@Before
public void authenticateCurrentUser() {
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50");
SecurityContextHolder.getContext().setAuthentication(auth);
public SwitchUserProcessingFilterTests() {
}
@After
public void clearContext() {
SecurityContextHolder.clearContext();
public SwitchUserProcessingFilterTests(String arg0) {
super(arg0);
}
//~ Methods ========================================================================================================
protected void tearDown() throws Exception {
SecurityContextHolder.clearContext();
}
private MockHttpServletRequest createMockSwitchRequest() {
@@ -72,122 +76,181 @@ public class SwitchUserProcessingFilterTests {
return request;
}
private Authentication switchToUser(String name) {
MockHttpServletRequest request = new MockHttpServletRequest();
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, name);
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setUserDetailsService(new MockUserDetailsService());
return filter.attemptSwitchUser(request);
}
@Test
public void requiresExitUserMatchesCorrectly() {
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setExitUserUrl("/j_spring_security_my_exit_user");
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/j_spring_security_my_exit_user");
assertTrue(filter.requiresExitUser(request));
}
@Test
public void requiresSwitchMatchesCorrectly() {
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setSwitchUserUrl("/j_spring_security_my_switch_user");
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/j_spring_security_my_switch_user");
assertTrue(filter.requiresSwitchUser(request));
}
@Test(expected=UsernameNotFoundException.class)
public void attemptSwitchToUnknownUserFails() throws Exception {
public void testAttemptSwitchToUnknownUser() throws Exception {
// set current user
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50");
SecurityContextHolder.getContext().setAuthentication(auth);
MockHttpServletRequest request = new MockHttpServletRequest();
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, "user-that-doesnt-exist");
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setUserDetailsService(new MockUserDetailsService());
filter.attemptSwitchUser(request);
filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
try {
Authentication result = filter.attemptSwitchUser(request);
fail("Should not be able to switch to unknown user");
} catch (UsernameNotFoundException expected) {}
}
@Test(expected=DisabledException.class)
public void attemptSwitchToUserThatIsDisabledFails() throws Exception {
switchToUser("mcgarrett");
}
public void testAttemptSwitchToUserThatIsDisabled() throws Exception {
// set current user
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50");
SecurityContextHolder.getContext().setAuthentication(auth);
@Test(expected=AccountExpiredException.class)
public void attemptSwitchToUserWithAccountExpiredFails() throws Exception {
switchToUser("wofat");
}
@Test(expected=CredentialsExpiredException.class)
public void attemptSwitchToUserWithExpiredCredentialsFails() throws Exception {
switchToUser("steve");
}
@Test(expected=UsernameNotFoundException.class)
public void switchUserWithNullUsernameThrowsException() throws Exception {
switchToUser(null);
}
@Test
public void attemptSwitchUserIsSuccessfulWithValidUser() throws Exception {
assertNotNull(switchToUser("jacklord"));
}
@Test
public void switchToLockedAccountCausesRedirectToSwitchFailureUrl() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/j_spring_security_switch_user");
// this user is disabled
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, "mcgarrett");
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
try {
Authentication result = filter.attemptSwitchUser(request);
fail("Should not be able to switch to disabled user");
} catch (DisabledException expected) {
// user should be disabled
}
}
public void testAttemptSwitchToUserWithAccountExpired() throws Exception {
// set current user
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50");
SecurityContextHolder.getContext().setAuthentication(auth);
MockHttpServletRequest request = new MockHttpServletRequest();
// this user is disabled
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, "wofat");
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
try {
Authentication result = filter.attemptSwitchUser(request);
fail("Should not be able to switch to user with expired account");
} catch (AccountExpiredException expected) {
// expected user account expired
}
}
public void testAttemptSwitchToUserWithExpiredCredentials() throws Exception {
// set current user
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50");
SecurityContextHolder.getContext().setAuthentication(auth);
MockHttpServletRequest request = new MockHttpServletRequest();
// this user is disabled
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, "steve");
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
try {
Authentication result = filter.attemptSwitchUser(request);
fail("Should not be able to switch to user with expired account");
} catch (CredentialsExpiredException expected) {
// user credentials expired
}
}
public void testAttemptSwitchUser() throws Exception {
// set current user
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50");
SecurityContextHolder.getContext().setAuthentication(auth);
MockHttpServletRequest request = new MockHttpServletRequest();
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, "jacklord");
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
Authentication result = filter.attemptSwitchUser(request);
assertTrue(result != null);
}
public void testSwitchToLockedAccountCausesRedirectToSwitchFailureUrl() throws Exception {
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50");
SecurityContextHolder.getContext().setAuthentication(auth);
MockHttpServletRequest request = createMockSwitchRequest();
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, "mcgarrett");
MockHttpServletResponse response = new MockHttpServletResponse();
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setUserDetailsService(new MockUserDetailsService());
filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
// Check it with no url set (should get a text response)
// Check it with no url set
filter.doFilterHttp(request, response, new MockFilterChain(false));
assertEquals("Switch user failed: User is disabled", response.getContentAsString());
// Now check for the redirect
request.setContextPath("/mywebapp");
request.setRequestURI("/mywebapp/j_spring_security_switch_user");
filter.setSwitchFailureUrl("/switchfailed");
response = new MockHttpServletResponse();
filter.doFilterHttp(request, response, new MockFilterChain(true));
filter.doFilterHttp(request, response, new MockFilterChain(false));
assertEquals("/switchfailed", response.getRedirectedUrl());
assertEquals("/mywebapp/switchfailed", response.getRedirectedUrl());
assertEquals("/switchfailed", FieldUtils.getFieldValue(filter, "switchFailureUrl"));
}
@Test(expected=IllegalArgumentException.class)
public void configMissingUserDetailsServiceFails() throws Exception {
public void testIfSwitchUserWithNullUsernameThrowsException() throws Exception {
// set current user
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50");
SecurityContextHolder.getContext().setAuthentication(auth);
MockHttpServletRequest request = new MockHttpServletRequest();
String username = null;
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, username);
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
Authentication result = null ;
try {
result = filter.attemptSwitchUser(request);
fail("UsernameNotFoundException should have been thrown");
} catch (UsernameNotFoundException e) {
}
assertFalse(result != null);
}
public void testBadConfigMissingAuthenticationDao() {
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setSwitchUserUrl("/j_spring_security_switch_user");
filter.setExitUserUrl("/j_spring_security_exit_user");
filter.setTargetUrl("/main.jsp");
filter.afterPropertiesSet();
try {
filter.afterPropertiesSet();
fail("Expect to fail due to missing 'authenticationDao'");
} catch (Exception expected) {
// expected exception
}
}
@Test(expected=IllegalArgumentException.class)
public void testBadConfigMissingTargetUrl() throws Exception {
public void testBadConfigMissingTargetUrl() {
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setUserDetailsService(new MockUserDetailsService());
filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
filter.setSwitchUserUrl("/j_spring_security_switch_user");
filter.setExitUserUrl("/j_spring_security_exit_user");
filter.afterPropertiesSet();
try {
filter.afterPropertiesSet();
fail("Expect to fail due to missing 'targetUrl'");
} catch (Exception expected) {
// expected exception
}
}
@Test
public void defaultProcessesFilterUrlMatchesUrlWithPathParameter() {
public void testDefaultProcessesFilterUrlWithPathParameter() {
MockHttpServletRequest request = createMockSwitchRequest();
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setSwitchUserUrl("/j_spring_security_switch_user");
@@ -196,8 +259,7 @@ public class SwitchUserProcessingFilterTests {
assertTrue(filter.requiresSwitchUser(request));
}
@Test
public void exitUserJackLordToDanoSucceeds() throws Exception {
public void testExitRequestUserJackLordToDano() throws Exception {
// original user
GrantedAuthority[] auths = {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")};
UsernamePasswordAuthenticationToken source = new UsernamePasswordAuthenticationToken("dano", "hawaii50", auths);
@@ -212,17 +274,23 @@ public class SwitchUserProcessingFilterTests {
SecurityContextHolder.getContext().setAuthentication(admin);
// http request
MockHttpServletRequest request = createMockSwitchRequest();
request.setRequestURI("/j_spring_security_exit_user");
// http response
MockHttpServletResponse response = new MockHttpServletResponse();
// setup filter
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setUserDetailsService(new MockUserDetailsService());
filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
filter.setExitUserUrl("/j_spring_security_exit_user");
filter.setTargetUrl("/webapp/someOtherUrl");
MockFilterChain chain = new MockFilterChain(true);
// run 'exit'
filter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain(false));
filter.doFilter(request, response, chain);
// check current user, should be back to original user (dano)
Authentication targetAuth = SecurityContextHolder.getContext().getAuthentication();
@@ -230,44 +298,33 @@ public class SwitchUserProcessingFilterTests {
assertEquals("dano", targetAuth.getPrincipal());
}
@Test(expected=AuthenticationException.class)
public void exitUserWithNoCurrentUserFails() throws Exception {
public void testExitUserWithNoCurrentUser() throws Exception {
// no current user in secure context
SecurityContextHolder.clearContext();
SecurityContextHolder.getContext().setAuthentication(null);
// http request
MockHttpServletRequest request = createMockSwitchRequest();
request.setRequestURI("/j_spring_security_exit_user");
// setup filter
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setUserDetailsService(new MockUserDetailsService());
filter.setExitUserUrl("/j_spring_security_exit_user");
// run 'exit', expect fail due to no current user
filter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain(false));
}
@Test
public void redirectToTargetUrlIsCorrect() throws Exception {
MockHttpServletRequest request = createMockSwitchRequest();
request.setContextPath("/webapp");
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, "jacklord");
request.setRequestURI("/webapp/j_spring_security_switch_user");
// http response
MockHttpServletResponse response = new MockHttpServletResponse();
// setup filter
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setSwitchUserUrl("/j_spring_security_switch_user");
filter.setTargetUrl("/someOtherUrl");
filter.setUserDetailsService(new MockUserDetailsService());
filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
filter.setExitUserUrl("/j_spring_security_exit_user");
filter.doFilter(request, response, new MockFilterChain(false));
MockFilterChain chain = new MockFilterChain(true);
assertEquals("/webapp/someOtherUrl", response.getRedirectedUrl());
// run 'exit', expect fail due to no current user
try {
filter.doFilter(request, response, chain);
fail("Cannot exit from a user with no current user set!");
} catch (AuthenticationException expected) {}
}
@Test
public void redirectOmitsContextPathIfUseRelativeContextSet() throws Exception {
public void testRedirectToTargetUrl() throws Exception {
// set current user
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50");
SecurityContextHolder.getContext().setAuthentication(auth);
@@ -278,19 +335,65 @@ public class SwitchUserProcessingFilterTests {
request.setRequestURI("/webapp/j_spring_security_switch_user");
MockHttpServletResponse response = new MockHttpServletResponse();
MockFilterChain chain = new MockFilterChain(true);
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setSwitchUserUrl("/j_spring_security_switch_user");
filter.setTargetUrl("/someOtherUrl");
filter.setUserDetailsService(new MockUserDetailsService());
filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
filter.doFilter(request, response, chain);
assertEquals("/webapp/someOtherUrl", response.getRedirectedUrl());
}
public void testRedirectOmitsContextPathIfUseRelativeContextSet() throws Exception {
// set current user
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50");
SecurityContextHolder.getContext().setAuthentication(auth);
MockHttpServletRequest request = createMockSwitchRequest();
request.setContextPath("/webapp");
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, "jacklord");
request.setRequestURI("/webapp/j_spring_security_switch_user");
MockHttpServletResponse response = new MockHttpServletResponse();
MockFilterChain chain = new MockFilterChain(true);
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setSwitchUserUrl("/j_spring_security_switch_user");
filter.setTargetUrl("/someOtherUrl");
filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
filter.setUseRelativeContext(true);
filter.doFilter(request, response, new MockFilterChain(false));
filter.doFilter(request, response, chain);
assertEquals("/someOtherUrl", response.getRedirectedUrl());
}
@Test
public void testRequiresExitUser() {
// filter
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setExitUserUrl("/j_spring_security_exit_user");
// request
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/j_spring_security_exit_user");
assertTrue(filter.requiresExitUser(request));
}
public void testRequiresSwitch() {
// filter
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setSwitchUserUrl("/j_spring_security_switch_user");
// request
MockHttpServletRequest request = createMockSwitchRequest();
assertTrue(filter.requiresSwitchUser(request));
}
public void testSwitchRequestFromDanoToJackLord() throws Exception {
// set current user
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50");
@@ -306,7 +409,7 @@ public class SwitchUserProcessingFilterTests {
// setup filter
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setUserDetailsService(new MockUserDetailsService());
filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
filter.setSwitchUserUrl("/j_spring_security_switch_user");
filter.setTargetUrl("/webapp/someOtherUrl");
@@ -322,8 +425,7 @@ public class SwitchUserProcessingFilterTests {
assertEquals("jacklord", ((User) targetAuth.getPrincipal()).getUsername());
}
@Test
public void modificationOfAuthoritiesWorks() {
public void testModificationOfAuthoritiesWorks() {
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50");
SecurityContextHolder.getContext().setAuthentication(auth);
@@ -331,7 +433,7 @@ public class SwitchUserProcessingFilterTests {
request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, "jacklord");
SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
filter.setUserDetailsService(new MockUserDetailsService());
filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
filter.setSwitchUserAuthorityChanger(new SwitchUserAuthorityChanger() {
public List modifyGrantedAuthorities(UserDetails targetUser, Authentication currentAuthentication, List authoritiesToBeGranted) {
List auths = new ArrayList();
@@ -349,10 +451,11 @@ public class SwitchUserProcessingFilterTests {
//~ Inner Classes ==================================================================================================
private class MockUserDetailsService implements UserDetailsService {
private class MockAuthenticationDaoUserJackLord implements UserDetailsService {
private String password = "hawaii50";
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
// jacklord, dano (active)
// mcgarrett (disabled)
// wofat (account expired)

Some files were not shown because too many files have changed in this diff Show More