Bläddra i källkod

SEC-576: Tidied up code, added preauth sample demo app.

Luke Taylor 17 år sedan
förälder
incheckning
837ecd85ec
27 ändrade filer med 1043 tillägg och 637 borttagningar
  1. 65 62
      core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedAuthenticationProvider.java
  2. 53 52
      core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedAuthenticationToken.java
  3. 7 4
      core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedGrantedAuthoritiesRetriever.java
  4. 8 5
      core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedGrantedAuthoritiesSetter.java
  5. 3 2
      core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedGrantedAuthoritiesUserDetailsService.java
  6. 5 2
      core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedUserDetailsService.java
  7. 6 3
      core/src/main/java/org/springframework/security/providers/preauth/UserDetailsByNameServiceWrapper.java
  8. 10 7
      core/src/main/java/org/springframework/security/rolemapping/MappableRolesRetriever.java
  9. 14 12
      core/src/main/java/org/springframework/security/rolemapping/Roles2GrantedAuthoritiesMapper.java
  10. 19 16
      core/src/main/java/org/springframework/security/rolemapping/SimpleMappableRolesRetriever.java
  11. 82 82
      core/src/main/java/org/springframework/security/rolemapping/SimpleRoles2GrantedAuthoritiesMapper.java
  12. 145 143
      core/src/main/java/org/springframework/security/rolemapping/XmlMappableRolesRetriever.java
  13. 109 108
      core/src/main/java/org/springframework/security/ui/preauth/AbstractPreAuthenticatedProcessingFilter.java
  14. 5 2
      core/src/main/java/org/springframework/security/ui/preauth/PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.java
  15. 9 9
      core/src/main/java/org/springframework/security/ui/preauth/PreAuthenticatedProcessingFilterEntryPoint.java
  16. 70 70
      core/src/main/java/org/springframework/security/ui/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.java
  17. 21 22
      core/src/main/java/org/springframework/security/ui/preauth/j2ee/J2eePreAuthenticatedProcessingFilter.java
  18. 29 31
      core/src/main/java/org/springframework/security/ui/preauth/j2ee/WebXmlMappableRolesRetriever.java
  19. 5 5
      core/src/test/java/org/springframework/security/ui/preauth/PreAuthenticatedProcesingFilterEntryPointTests.java
  20. 116 0
      samples/preauth/pom.xml
  21. 3 0
      samples/preauth/realm.properties
  22. 125 0
      samples/preauth/src/main/webapp/WEB-INF/applicationContext-security.xml
  23. 20 0
      samples/preauth/src/main/webapp/WEB-INF/classes/log4j.properties
  24. 73 0
      samples/preauth/src/main/webapp/WEB-INF/web.xml
  25. 11 0
      samples/preauth/src/main/webapp/index.jsp
  26. 15 0
      samples/preauth/src/main/webapp/secure/extreme/index.jsp
  27. 15 0
      samples/preauth/src/main/webapp/secure/index.jsp

+ 65 - 62
core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedAuthenticationProvider.java

@@ -16,74 +16,77 @@ import org.springframework.util.Assert;
  * Processes a pre-authenticated authentication request. The request will
  * typically originate from a {@link org.springframework.security.ui.preauth.AbstractPreAuthenticatedProcessingFilter}
  * subclass.
- * </p>
- * 
+ *
  * <p>
  * This authentication provider will not perform any checks on authentication
  * requests, as they should already be pre- authenticated. However, the
  * PreAuthenticatedUserDetailsService implementation may still throw for exampe
  * a UsernameNotFoundException.
- * </p>
+ *
+ * @author Ruud Senden
+ * @since 2.0
  */
 public class PreAuthenticatedAuthenticationProvider implements AuthenticationProvider, InitializingBean, Ordered {
-	private static final Log LOG = LogFactory.getLog(PreAuthenticatedAuthenticationProvider.class);
-
-	private PreAuthenticatedUserDetailsService preAuthenticatedUserDetailsService = null;
-
-	private int order = -1; // default: same as non-ordered
-
-	/**
-	 * Check whether all required properties have been set.
-	 */
-	public void afterPropertiesSet() {
-		Assert.notNull(preAuthenticatedUserDetailsService, "A PreAuthenticatedUserDetailsService must be set");
-	}
-
-	/**
-	 * Authenticate the given PreAuthenticatedAuthenticationToken.
-	 */
-	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
-		if (!supports(authentication.getClass())) {
-			return null;
-		}
-
-		if (LOG.isDebugEnabled()) {
-			LOG.debug("PreAuthenticated authentication request: " + authentication);
-		}
-
-		UserDetails ud = preAuthenticatedUserDetailsService.getUserDetails((PreAuthenticatedAuthenticationToken) authentication);
-		if (ud == null) {
-			return null;
-		}
-		PreAuthenticatedAuthenticationToken result =
+    private static final Log logger = LogFactory.getLog(PreAuthenticatedAuthenticationProvider.class);
+
+    private PreAuthenticatedUserDetailsService preAuthenticatedUserDetailsService = null;
+
+    private int order = -1; // default: same as non-ordered
+
+    /**
+     * Check whether all required properties have been set.
+     */
+    public void afterPropertiesSet() {
+        Assert.notNull(preAuthenticatedUserDetailsService, "A PreAuthenticatedUserDetailsService must be set");
+    }
+
+    /**
+     * Authenticate the given PreAuthenticatedAuthenticationToken.
+     */
+    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+        if (!supports(authentication.getClass())) {
+            return null;
+        }
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("PreAuthenticated authentication request: " + authentication);
+        }
+
+        UserDetails ud = preAuthenticatedUserDetailsService.getUserDetails((PreAuthenticatedAuthenticationToken) authentication);
+
+        if (ud == null) {
+            return null;
+        }
+
+        PreAuthenticatedAuthenticationToken result =
                 new PreAuthenticatedAuthenticationToken(ud, authentication.getCredentials(), ud.getAuthorities());
-		result.setDetails(authentication.getDetails());
-
-		return result;
-
-	}
-
-	/**
-	 * Indicate that this provider only supports PreAuthenticatedAuthenticationToken (sub)classes.
-	 */
-	public boolean supports(Class authentication) {
-		return PreAuthenticatedAuthenticationToken.class.isAssignableFrom(authentication);
-	}
-
-	/**
-	 * Set the PreAuthenticatedUserDetailsServices to be used.
-	 * 
-	 * @param aPreAuthenticatedUserDetailsService
-	 */
-	public void setPreAuthenticatedUserDetailsService(PreAuthenticatedUserDetailsService aPreAuthenticatedUserDetailsService) {
-		this.preAuthenticatedUserDetailsService = aPreAuthenticatedUserDetailsService;
-	}
-
-	public int getOrder() {
-		return order;
-	}
-
-	public void setOrder(int i) {
-		order = i;
-	}
+        result.setDetails(authentication.getDetails());
+
+        return result;
+
+    }
+
+    /**
+     * Indicate that this provider only supports PreAuthenticatedAuthenticationToken (sub)classes.
+     */
+    public boolean supports(Class authentication) {
+        return PreAuthenticatedAuthenticationToken.class.isAssignableFrom(authentication);
+    }
+
+    /**
+     * Set the PreAuthenticatedUserDetailsServices to be used.
+     *
+     * @param aPreAuthenticatedUserDetailsService
+     */
+    public void setPreAuthenticatedUserDetailsService(PreAuthenticatedUserDetailsService aPreAuthenticatedUserDetailsService) {
+        this.preAuthenticatedUserDetailsService = aPreAuthenticatedUserDetailsService;
+    }
+
+    public int getOrder() {
+        return order;
+    }
+
+    public void setOrder(int i) {
+        order = i;
+    }
 }

+ 53 - 52
core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedAuthenticationToken.java

@@ -7,64 +7,65 @@ import org.springframework.security.GrantedAuthority;
 /**
  * {@link org.springframework.security.Authentication} implementation for pre-authenticated
  * authentication.
+ *
+ * @author Ruud Senden
+ * @since 2.0
  */
 public class PreAuthenticatedAuthenticationToken extends AbstractAuthenticationToken {
-	private static final long serialVersionUID = 1L;
+    private Object principal;
 
-	private Object principal;
+    private Object credentials;
 
-	private Object credentials;
+    /**
+     * Constructor used for an authentication request. The {@link
+     * org.springframework.security.Authentication#isAuthenticated()} will return
+     * <code>false</code>.
+     *
+     * @TODO Should we have only a single credentials parameter here? For
+     *       example for X509 the certificate is used as credentials, while
+     *       currently a J2EE username is specified as a principal but could as
+     *       well be set as credentials.
+     *
+     * @param aPrincipal
+     *            The pre-authenticated principal
+     * @param aCredentials
+     *            The pre-authenticated credentials
+     */
+    public PreAuthenticatedAuthenticationToken(Object aPrincipal, Object aCredentials) {
+        super(null);
+        this.principal = aPrincipal;
+        this.credentials = aCredentials;
+    }
 
-	/**
-	 * Constructor used for an authentication request. The {@link
-	 * org.springframework.security.Authentication#isAuthenticated()} will return
-	 * <code>false</code>.
-	 * 
-	 * @TODO Should we have only a single credentials parameter here? For
-	 *       example for X509 the certificate is used as credentials, while
-	 *       currently a J2EE username is specified as a principal but could as
-	 *       well be set as credentials.
-	 * 
-	 * @param aPrincipal
-	 *            The pre-authenticated principal
-	 * @param aCredentials
-	 *            The pre-authenticated credentials
-	 */
-	public PreAuthenticatedAuthenticationToken(Object aPrincipal, Object aCredentials) {
-		super(null);
-		this.principal = aPrincipal;
-		this.credentials = aCredentials;
-	}
+    /**
+     * Constructor used for an authentication response. The {@link
+     * org.springframework.security.Authentication#isAuthenticated()} will return
+     * <code>true</code>.
+     *
+     * @param aPrincipal
+     *            The authenticated principal
+     * @param anAuthorities
+     *            The granted authorities
+     */
+    public PreAuthenticatedAuthenticationToken(Object aPrincipal, Object aCredentials, GrantedAuthority[] anAuthorities) {
+        super(anAuthorities);
+        this.principal = aPrincipal;
+        this.credentials = aCredentials;
+        setAuthenticated(true);
+    }
 
-	/**
-	 * Constructor used for an authentication response. The {@link
-	 * org.springframework.security.Authentication#isAuthenticated()} will return
-	 * <code>true</code>.
-	 * 
-	 * @param aPrincipal
-	 *            The authenticated principal
-	 * @param anAuthorities
-	 *            The granted authorities
-	 */
-	public PreAuthenticatedAuthenticationToken(Object aPrincipal, Object aCredentials, GrantedAuthority[] anAuthorities) {
-		super(anAuthorities);
-		this.principal = aPrincipal;
-		this.credentials = aCredentials;
-		setAuthenticated(true);
-	}
+    /**
+     * Get the credentials
+     */
+    public Object getCredentials() {
+        return this.credentials;
+    }
 
-	/**
-	 * Get the credentials
-	 */
-	public Object getCredentials() {
-		return this.credentials;
-	}
-
-	/**
-	 * Get the principal
-	 */
-	public Object getPrincipal() {
-		return this.principal;
-	}
+    /**
+     * Get the principal
+     */
+    public Object getPrincipal() {
+        return this.principal;
+    }
 
 }

+ 7 - 4
core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedGrantedAuthoritiesRetriever.java

@@ -6,10 +6,13 @@ import org.springframework.security.GrantedAuthority;
 /**
  * Interface that allows for retrieval of a list of pre-authenticated Granted
  * Authorities.
+ *
+ * @author Ruud Senden
+ * @since 2.0
  */
 public interface PreAuthenticatedGrantedAuthoritiesRetriever {
-	/**
-	 * @return GrantedAuthority[] List of pre-authenticated GrantedAuthorities
-	 */
-	public GrantedAuthority[] getPreAuthenticatedGrantedAuthorities();
+    /**
+     * @return GrantedAuthority[] List of pre-authenticated GrantedAuthorities
+     */
+    GrantedAuthority[] getPreAuthenticatedGrantedAuthorities();
 }

+ 8 - 5
core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedGrantedAuthoritiesSetter.java

@@ -8,11 +8,14 @@ import org.springframework.security.GrantedAuthority;
  * actually being used by the PreAuthenticatedAuthenticationProvider or one of
  * its related classes, but may be useful for classes that also implement
  * PreAuthenticatedGrantedAuthoritiesRetriever.
+ *
+ * @author Ruud Senden
+ * @since 2.0
  */
 public interface PreAuthenticatedGrantedAuthoritiesSetter {
-	/**
-	 * @param aPreAuthenticatedGrantedAuthorities
-	 *            The pre-authenticated GrantedAuthority[] to set
-	 */
-	public void setPreAuthenticatedGrantedAuthorities(GrantedAuthority[] aPreAuthenticatedGrantedAuthorities);
+    /**
+     * @param aPreAuthenticatedGrantedAuthorities
+     *            The pre-authenticated GrantedAuthority[] to set
+     */
+    void setPreAuthenticatedGrantedAuthorities(GrantedAuthority[] aPreAuthenticatedGrantedAuthorities);
 }

+ 3 - 2
core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedGrantedAuthoritiesUserDetailsService.java

@@ -17,14 +17,15 @@ import org.springframework.util.Assert;
  * PreAuthenticatedAuthenticationProvider anyway), and the Granted Authorities
  * are retrieved from the details object as returned by
  * PreAuthenticatedAuthenticationToken.getDetails().
- * </p>
  * 
  * <p>
  * The details object as returned by
  * PreAuthenticatedAuthenticationToken.getDetails() must implement the
  * PreAuthenticatedGrantedAuthoritiesRetriever interface for this implementation
  * to work.
- * </p>
+ *
+ * @author Ruud Senden
+ * @since 2.0
  */
 public class PreAuthenticatedGrantedAuthoritiesUserDetailsService implements PreAuthenticatedUserDetailsService {
 	/**

+ 5 - 2
core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedUserDetailsService.java

@@ -7,11 +7,14 @@ import org.springframework.security.userdetails.UserDetails;
 /**
  * Interface that allows for retrieving a UserDetails object based on a
  * PreAuthenticatedAuthenticationToken object.
+ *
+ * @author Ruud Senden
+ * @since 2.0
  */
 public interface PreAuthenticatedUserDetailsService {
 
 	/**
-	 * 
+	 *
 	 * @param aPreAuthenticatedAuthenticationToken
 	 *            The pre-authenticated authentication token
 	 * @return UserDetails for the given authentication token.
@@ -19,6 +22,6 @@ public interface PreAuthenticatedUserDetailsService {
 	 *             if no user details can be found for the given authentication
 	 *             token
 	 */
-	public UserDetails getUserDetails(PreAuthenticatedAuthenticationToken aPreAuthenticatedAuthenticationToken)
+	UserDetails getUserDetails(PreAuthenticatedAuthenticationToken aPreAuthenticatedAuthenticationToken)
 			throws UsernameNotFoundException;
 }

+ 6 - 3
core/src/main/java/org/springframework/security/providers/preauth/UserDetailsByNameServiceWrapper.java

@@ -9,15 +9,18 @@ import org.springframework.util.Assert;
 
 /**
  * This implementation for PreAuthenticatedUserDetailsService wraps a regular
- * Acegi UserDetailsService implementation, to retrieve a UserDetails object
+ * Spring Security UserDetailsService implementation, to retrieve a UserDetails object
  * based on the user name contained in a PreAuthenticatedAuthenticationToken.
+ *
+ * @author Ruud Senden
+ * @since 2.0
  */
 public class UserDetailsByNameServiceWrapper implements PreAuthenticatedUserDetailsService, InitializingBean {
 	private UserDetailsService userDetailsService = null;
 
 	/**
 	 * Check whether all required properties have been set.
-	 * 
+	 *
 	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
 	 */
 	public void afterPropertiesSet() throws Exception {
@@ -35,7 +38,7 @@ public class UserDetailsByNameServiceWrapper implements PreAuthenticatedUserDeta
 
 	/**
 	 * Set the wrapped UserDetailsService implementation
-	 * 
+	 *
 	 * @param aUserDetailsService
 	 *            The wrapped UserDetailsService to set
 	 */

+ 10 - 7
core/src/main/java/org/springframework/security/rolemapping/MappableRolesRetriever.java

@@ -4,13 +4,16 @@ package org.springframework.security.rolemapping;
  * Interface to be implemented by classes that can retrieve a list of mappable
  * roles (for example the list of all available J2EE roles in a web or EJB
  * application).
+ *
+ * @author Ruud Senden
+ * @since 2.0
  */
 public interface MappableRolesRetriever {
-	/**
-	 * Implementations of this method should return a list of all mappable
-	 * roles.
-	 * 
-	 * @return String[] containg list of all mappable roles
-	 */
-	public String[] getMappableRoles();
+    /**
+     * Implementations of this method should return a list of all mappable
+     * roles.
+     *
+     * @return list of all mappable roles
+     */
+    String[] getMappableRoles();
 }

+ 14 - 12
core/src/main/java/org/springframework/security/rolemapping/Roles2GrantedAuthoritiesMapper.java

@@ -5,18 +5,20 @@ import org.springframework.security.GrantedAuthority;
 /**
  * Interface to be implemented by classes that can map a list of roles to a list
  * of Acegi GrantedAuthorities.
+ *
+ * @author Ruud Senden
+ * @since 2.0
  */
 public interface Roles2GrantedAuthoritiesMapper {
-	/**
-	 * Implementations of this method should map the given list of roles to a
-	 * list of Acegi GrantedAuthorities. There are no restrictions for the
-	 * mapping process; a single role can be mapped to multiple Acegi
-	 * GrantedAuthorities, all roles can be mapped to a single Acegi
-	 * GrantedAuthority, some roles may not be mapped, etc.
-	 * 
-	 * @param String[]
-	 *            containing list of roles
-	 * @return GrantedAuthority[] containing list of mapped GrantedAuthorities
-	 */
-	public GrantedAuthority[] getGrantedAuthorities(String[] roles);
+    /**
+     * Implementations of this method should map the given list of roles to a
+     * list of Acegi GrantedAuthorities. There are no restrictions for the
+     * mapping process; a single role can be mapped to multiple Acegi
+     * GrantedAuthorities, all roles can be mapped to a single Acegi
+     * GrantedAuthority, some roles may not be mapped, etc.
+     *
+     * @param roles the roles to be mapped
+     * @return the list of mapped GrantedAuthorities
+     */
+    public GrantedAuthority[] getGrantedAuthorities(String[] roles);
 }

+ 19 - 16
core/src/main/java/org/springframework/security/rolemapping/SimpleMappableRolesRetriever.java

@@ -6,25 +6,28 @@ import org.springframework.util.Assert;
  * This class implements the MappableRolesRetriever interface by just returning
  * a list of mappable roles as previously set using the corresponding setter
  * method.
+ *
+ * @author Ruud Senden
+ * @since 2.0
  */
 public class SimpleMappableRolesRetriever implements MappableRolesRetriever {
-	private String[] mappableRoles = null;
+    private String[] mappableRoles = null;
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.springframework.security.rolemapping.MappableRolesRetriever#getMappableRoles()
-	 */
-	public String[] getMappableRoles() {
-		Assert.notNull(mappableRoles, "No mappable roles have been set");
-		String[] copy = new String[mappableRoles.length];
-		System.arraycopy(mappableRoles, 0, copy, 0, copy.length);
-		return copy;
-	}
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.springframework.security.rolemapping.MappableRolesRetriever#getMappableRoles()
+     */
+    public String[] getMappableRoles() {
+        Assert.notNull(mappableRoles, "No mappable roles have been set");
+        String[] copy = new String[mappableRoles.length];
+        System.arraycopy(mappableRoles, 0, copy, 0, copy.length);
+        return copy;
+    }
 
-	public void setMappableRoles(String[] aMappableRoles) {
-		this.mappableRoles = new String[aMappableRoles.length];
-		System.arraycopy(aMappableRoles, 0, mappableRoles, 0, mappableRoles.length);
-	}
+    public void setMappableRoles(String[] aMappableRoles) {
+        this.mappableRoles = new String[aMappableRoles.length];
+        System.arraycopy(aMappableRoles, 0, mappableRoles, 0, mappableRoles.length);
+    }
 
 }

+ 82 - 82
core/src/main/java/org/springframework/security/rolemapping/SimpleRoles2GrantedAuthoritiesMapper.java

@@ -14,92 +14,92 @@ import org.springframework.util.Assert;
  * one-on-one mapping from roles to Acegi GrantedAuthorities. Optionally a
  * prefix can be added, and the role name can be converted to upper or lower
  * case.
- * </p>
- * 
  * <p>
  * By default, the role is prefixed with "ROLE_" unless it already starts with
  * "ROLE_", and no case conversion is done.
- * </p>
+ *
+ * @author Ruud Senden
+ * @since 2.0
  */
 public class SimpleRoles2GrantedAuthoritiesMapper implements Roles2GrantedAuthoritiesMapper, InitializingBean {
-	private String rolePrefix = "ROLE_";
-
-	private boolean convertRoleToUpperCase = false;
-
-	private boolean convertRoleToLowerCase = false;
-
-	private boolean addPrefixIfAlreadyExisting = false;
-
-	/**
-	 * Check whether all properties have been set to correct values.
-	 */
-	public void afterPropertiesSet() throws Exception {
-		Assert.isTrue(!(isConvertRoleToUpperCase() && isConvertRoleToLowerCase()),
-				"Either convertRoleToUpperCase or convertRoleToLowerCase can be set to true, but not both");
-	}
-
-	/**
-	 * Map the given list of roles one-on-one to Acegi GrantedAuthorities.
-	 */
-	public GrantedAuthority[] getGrantedAuthorities(String[] roles) {
-		GrantedAuthority[] result = new GrantedAuthority[roles.length];
-		for (int i = 0; i < roles.length; i++) {
-			result[i] = getGrantedAuthority(roles[i]);
-		}
-		return result;
-	}
-
-	/**
-	 * Map the given role ono-on-one to an Acegi GrantedAuthority, optionally
-	 * doing case conversion and/or adding a prefix.
-	 * 
-	 * @param role
-	 *            The role for which to get a GrantedAuthority
-	 * @return GrantedAuthority representing the given role.
-	 */
-	private GrantedAuthority getGrantedAuthority(String role) {
-		if (isConvertRoleToLowerCase()) {
-			role = role.toLowerCase(Locale.getDefault());
-		} else if (isConvertRoleToUpperCase()) {
-			role = role.toUpperCase(Locale.getDefault());
-		}
-		if (isAddPrefixIfAlreadyExisting() || !role.startsWith(getRolePrefix())) {
-			return new GrantedAuthorityImpl(getRolePrefix() + role);
-		} else {
-			return new GrantedAuthorityImpl(role);
-		}
-	}
-
-	private boolean isConvertRoleToLowerCase() {
-		return convertRoleToLowerCase;
-	}
-
-	public void setConvertRoleToLowerCase(boolean b) {
-		convertRoleToLowerCase = b;
-	}
-
-	private boolean isConvertRoleToUpperCase() {
-		return convertRoleToUpperCase;
-	}
-
-	public void setConvertRoleToUpperCase(boolean b) {
-		convertRoleToUpperCase = b;
-	}
-
-	private String getRolePrefix() {
-		return rolePrefix == null ? "" : rolePrefix;
-	}
-
-	public void setRolePrefix(String string) {
-		rolePrefix = string;
-	}
-
-	private boolean isAddPrefixIfAlreadyExisting() {
-		return addPrefixIfAlreadyExisting;
-	}
-
-	public void setAddPrefixIfAlreadyExisting(boolean b) {
-		addPrefixIfAlreadyExisting = b;
-	}
+    private String rolePrefix = "ROLE_";
+
+    private boolean convertRoleToUpperCase = false;
+
+    private boolean convertRoleToLowerCase = false;
+
+    private boolean addPrefixIfAlreadyExisting = false;
+
+    /**
+     * Check whether all properties have been set to correct values.
+     */
+    public void afterPropertiesSet() throws Exception {
+        Assert.isTrue(!(isConvertRoleToUpperCase() && isConvertRoleToLowerCase()),
+                "Either convertRoleToUpperCase or convertRoleToLowerCase can be set to true, but not both");
+    }
+
+    /**
+     * Map the given list of roles one-on-one to Acegi GrantedAuthorities.
+     */
+    public GrantedAuthority[] getGrantedAuthorities(String[] roles) {
+        GrantedAuthority[] result = new GrantedAuthority[roles.length];
+        for (int i = 0; i < roles.length; i++) {
+            result[i] = getGrantedAuthority(roles[i]);
+        }
+        return result;
+    }
+
+    /**
+     * Map the given role ono-on-one to an Acegi GrantedAuthority, optionally
+     * doing case conversion and/or adding a prefix.
+     *
+     * @param role
+     *            The role for which to get a GrantedAuthority
+     * @return GrantedAuthority representing the given role.
+     */
+    private GrantedAuthority getGrantedAuthority(String role) {
+        if (isConvertRoleToLowerCase()) {
+            role = role.toLowerCase(Locale.getDefault());
+        } else if (isConvertRoleToUpperCase()) {
+            role = role.toUpperCase(Locale.getDefault());
+        }
+        if (isAddPrefixIfAlreadyExisting() || !role.startsWith(getRolePrefix())) {
+            return new GrantedAuthorityImpl(getRolePrefix() + role);
+        } else {
+            return new GrantedAuthorityImpl(role);
+        }
+    }
+
+    private boolean isConvertRoleToLowerCase() {
+        return convertRoleToLowerCase;
+    }
+
+    public void setConvertRoleToLowerCase(boolean b) {
+        convertRoleToLowerCase = b;
+    }
+
+    private boolean isConvertRoleToUpperCase() {
+        return convertRoleToUpperCase;
+    }
+
+    public void setConvertRoleToUpperCase(boolean b) {
+        convertRoleToUpperCase = b;
+    }
+
+    private String getRolePrefix() {
+        return rolePrefix == null ? "" : rolePrefix;
+    }
+
+    public void setRolePrefix(String string) {
+        rolePrefix = string;
+    }
+
+    private boolean isAddPrefixIfAlreadyExisting() {
+        return addPrefixIfAlreadyExisting;
+    }
+
+    public void setAddPrefixIfAlreadyExisting(boolean b) {
+        addPrefixIfAlreadyExisting = b;
+    }
 
 }

+ 145 - 143
core/src/main/java/org/springframework/security/rolemapping/XmlMappableRolesRetriever.java

@@ -28,154 +28,156 @@ import org.xml.sax.SAXException;
 /**
  * This implementation for the MappableRolesRetriever interface retrieves the
  * list of mappable roles from an XML file.
- * 
+ * <p>
  * This class is defined as abstract because it is too generic to be used
  * directly. As this class is usually used to read very specific XML files (e.g.
  * web.xml, ejb-jar.xml), subclasses should usually define the actual
  * XPath-expression to use, and define a more specifically named setter for the
  * XML InputStream (e.g. setWebXmlInputStream).
+ *
+ * @author Ruud Senden
+ * @since 2.0
  */
 public abstract class XmlMappableRolesRetriever implements MappableRolesRetriever, InitializingBean {
-	private static final Log LOG = LogFactory.getLog(XmlMappableRolesRetriever.class);
-
-	private String[] mappableRoles = null;
-
-	private InputStream xmlInputStream = null;
-
-	private String xpathExpression = null;
-
-	private boolean closeInputStream = true;
-
-	/**
-	 * Check whether all required properties have been set.
-	 */
-	public void afterPropertiesSet() throws Exception {
-		Assert.notNull(xmlInputStream, "An XML InputStream must be set");
-		Assert.notNull(xpathExpression, "An XPath expression must be set");
-		mappableRoles = getMappableRoles(xmlInputStream);
-	}
-
-	public String[] getMappableRoles() {
-		String[] copy = new String[mappableRoles.length];
-		System.arraycopy(mappableRoles, 0, copy, 0, copy.length);
-		return copy;
-	}
-
-	/**
-	 * Get the mappable roles from the specified XML document.
-	 */
-	private String[] getMappableRoles(InputStream aStream) {
-		if (LOG.isDebugEnabled()) {
-			LOG.debug("Reading mappable roles from XML document");
-		}
-		try {
-			Document doc = getDocument(aStream);
-			String[] roles = getMappableRoles(doc);
-			if (LOG.isDebugEnabled()) {
-				LOG.debug("Mappable roles from XML document: " + ArrayUtils.toString(roles));
-			}
-			return roles;
-		} finally {
-			if (closeInputStream) {
-				try {
-					aStream.close();
-				} catch (Exception e) {
-					LOG.debug("Input stream could not be closed", e);
-				}
-			}
-		}
-
-	}
-
-	/**
-	 * @return Document for the specified InputStream
-	 */
-	private Document getDocument(InputStream aStream) {
-		Document doc;
-		try {
-			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-			factory.setValidating(false);
-			DocumentBuilder db = factory.newDocumentBuilder();
-			db.setEntityResolver(new MyEntityResolver());
-			doc = db.parse(new IgnoreCloseInputStream(aStream));
-			return doc;
-		} catch (FactoryConfigurationError e) {
-			throw new RuntimeException("Unable to parse document object", e);
-		} catch (ParserConfigurationException e) {
-			throw new RuntimeException("Unable to parse document object", e);
-		} catch (SAXException e) {
-			throw new RuntimeException("Unable to parse document object", e);
-		} catch (IOException e) {
-			throw new RuntimeException("Unable to parse document object", e);
-		}
-	}
-
-	/**
-	 * @param doc
-	 *            The Document from which to read the list of roles
-	 * @return String[] the list of roles.
-	 * @throws JaxenException
-	 */
-	private String[] getMappableRoles(Document doc) {
-		try {
-			DOMXPath xpath = new DOMXPath(xpathExpression);
-			List roleElements = xpath.selectNodes(doc);
-			String[] roles = new String[roleElements.size()];
-			for (int i = 0; i < roles.length; i++) {
-				roles[i] = ((Node) roleElements.get(i)).getNodeValue();
-			}
-			return roles;
-		} catch (JaxenException e) {
-			throw new RuntimeException("Unable to retrieve mappable roles", e);
-		} catch (DOMException e) {
-			throw new RuntimeException("Unable to retrieve mappable roles", e);
-		}
-	}
-
-	/**
-	 * Subclasses should provide this method with a more specific name (e.g.
-	 * indicating the type of XML file the subclass expects, like
-	 * setWebXmlInputStream).
-	 */
-	protected void setXmlInputStream(InputStream aStream) {
-		this.xmlInputStream = aStream;
-	}
-
-	/**
-	 * Subclasses usually want to set an XPath expression by themselves (e.g.
-	 * not user-configurable). However subclasses may provide configuration
-	 * options to for example choose from a list of predefined XPath expressions
-	 * (e.g. to support multiple versions of the same type of XML file), as such
-	 * we provide a setter instead of mandatory constructor argument.
-	 */
-	protected void setXpathExpression(String anXpathExpression) {
-		xpathExpression = anXpathExpression;
-	}
-
-	/**
-	 * Define whether the provided InputStream must be closed after reading it.
-	 */
-	public void setCloseInputStream(boolean b) {
-		closeInputStream = b;
-	}
-
-	/**
-	 * We do not need to resolve external entities, so just return an empty
-	 * String.
-	 */
-	private static final class MyEntityResolver implements EntityResolver {
-		public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
-			return new InputSource(new StringReader(""));
-		}
-	}
-
-	public static final class IgnoreCloseInputStream extends FilterInputStream {
-		public IgnoreCloseInputStream(InputStream stream) {
-			super(stream);
-		}
-
-		public void close() throws IOException {
-			// do nothing
-		}
-	}
+    private static final Log LOG = LogFactory.getLog(XmlMappableRolesRetriever.class);
+
+    private String[] mappableRoles = null;
+
+    private InputStream xmlInputStream = null;
+
+    private String xpathExpression = null;
+
+    private boolean closeInputStream = true;
+
+    /**
+     * Check whether all required properties have been set.
+     */
+    public void afterPropertiesSet() throws Exception {
+        Assert.notNull(xmlInputStream, "An XML InputStream must be set");
+        Assert.notNull(xpathExpression, "An XPath expression must be set");
+        mappableRoles = getMappableRoles(xmlInputStream);
+    }
+
+    public String[] getMappableRoles() {
+        String[] copy = new String[mappableRoles.length];
+        System.arraycopy(mappableRoles, 0, copy, 0, copy.length);
+        return copy;
+    }
+
+    /**
+     * Get the mappable roles from the specified XML document.
+     */
+    private String[] getMappableRoles(InputStream aStream) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Reading mappable roles from XML document");
+        }
+        try {
+            Document doc = getDocument(aStream);
+            String[] roles = getMappableRoles(doc);
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Mappable roles from XML document: " + ArrayUtils.toString(roles));
+            }
+            return roles;
+        } finally {
+            if (closeInputStream) {
+                try {
+                    aStream.close();
+                } catch (Exception e) {
+                    LOG.debug("Input stream could not be closed", e);
+                }
+            }
+        }
+    }
+
+    /**
+     * @return Document for the specified InputStream
+     */
+    private Document getDocument(InputStream aStream) {
+        Document doc;
+        try {
+            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+            factory.setValidating(false);
+            DocumentBuilder db = factory.newDocumentBuilder();
+            db.setEntityResolver(new MyEntityResolver());
+            doc = db.parse(new IgnoreCloseInputStream(aStream));
+            return doc;
+        } catch (FactoryConfigurationError e) {
+            throw new RuntimeException("Unable to parse document object", e);
+        } catch (ParserConfigurationException e) {
+            throw new RuntimeException("Unable to parse document object", e);
+        } catch (SAXException e) {
+            throw new RuntimeException("Unable to parse document object", e);
+        } catch (IOException e) {
+            throw new RuntimeException("Unable to parse document object", e);
+        }
+    }
+
+    /**
+     * @param doc
+     *            The Document from which to read the list of roles
+     * @return String[] the list of roles.
+     * @throws JaxenException
+     */
+    private String[] getMappableRoles(Document doc) {
+        try {
+            DOMXPath xpath = new DOMXPath(xpathExpression);
+            List roleElements = xpath.selectNodes(doc);
+            String[] roles = new String[roleElements.size()];
+            for (int i = 0; i < roles.length; i++) {
+                roles[i] = ((Node) roleElements.get(i)).getNodeValue();
+            }
+            return roles;
+        } catch (JaxenException e) {
+            throw new RuntimeException("Unable to retrieve mappable roles", e);
+        } catch (DOMException e) {
+            throw new RuntimeException("Unable to retrieve mappable roles", e);
+        }
+    }
+
+    /**
+     * Subclasses should provide this method with a more specific name (e.g.
+     * indicating the type of XML file the subclass expects, like
+     * setWebXmlInputStream).
+     */
+    protected void setXmlInputStream(InputStream aStream) {
+        this.xmlInputStream = aStream;
+    }
+
+    /**
+     * Subclasses usually want to set an XPath expression by themselves (e.g.
+     * not user-configurable). However subclasses may provide configuration
+     * options to for example choose from a list of predefined XPath expressions
+     * (e.g. to support multiple versions of the same type of XML file), as such
+     * we provide a setter instead of mandatory constructor argument.
+     */
+    protected void setXpathExpression(String anXpathExpression) {
+        xpathExpression = anXpathExpression;
+    }
+
+    /**
+     * Define whether the provided InputStream must be closed after reading it.
+     */
+    public void setCloseInputStream(boolean b) {
+        closeInputStream = b;
+    }
+
+    /**
+     * We do not need to resolve external entities, so just return an empty
+     * String.
+     */
+    private static final class MyEntityResolver implements EntityResolver {
+        public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
+            return new InputSource(new StringReader(""));
+        }
+    }
+
+    public static final class IgnoreCloseInputStream extends FilterInputStream {
+        public IgnoreCloseInputStream(InputStream stream) {
+            super(stream);
+        }
+
+        public void close() throws IOException {
+            // do nothing
+        }
+    }
 }

+ 109 - 108
core/src/main/java/org/springframework/security/ui/preauth/AbstractPreAuthenticatedProcessingFilter.java

@@ -29,118 +29,119 @@ import org.springframework.util.Assert;
  * Base class for processing filters that handle pre-authenticated authentication requests. Subclasses must implement
  * the getPreAuthenticatedPrincipal() and getPreAuthenticatedCredentials() methods.
  *
+ * @author Luke Taylor
  * @author Ruud Senden
  * @since 2.0
  */
 public abstract class AbstractPreAuthenticatedProcessingFilter extends SpringSecurityFilter implements
         InitializingBean, ApplicationEventPublisherAware {
 
-    private static final Log LOG = LogFactory.getLog(AbstractPreAuthenticatedProcessingFilter.class);
-
-	private ApplicationEventPublisher eventPublisher = null;
-
-	private AuthenticationDetailsSource authenticationDetailsSource = new AuthenticationDetailsSourceImpl();
-
-	private AuthenticationManager authenticationManager = null;
-
-	/**
-	 * Check whether all required properties have been set.
-	 */
-	public void afterPropertiesSet() throws Exception {
-		Assert.notNull(authenticationManager, "An AuthenticationManager must be set");
-	}
-
-	/**
-	 * Try to authenticate a pre-authenticated user with Spring Security if the user has not yet been authenticated.
-	 */
-	public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
-		if (LOG.isDebugEnabled()) {
-			LOG.debug("Checking secure context token: " + SecurityContextHolder.getContext().getAuthentication());
-		}
-
-		if (SecurityContextHolder.getContext().getAuthentication() == null) {
-			doAuthenticate(request, response);
-		}
-		filterChain.doFilter(request, response);
-	}
-
-	/**
-	 * Do the actual authentication for a pre-authenticated user.
-	 */
-	private void doAuthenticate(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
-		Authentication authResult = null;
-
-		Object principal = getPreAuthenticatedPrincipal(httpRequest);
-		Object credentials = getPreAuthenticatedCredentials(httpRequest);
-
-		if (LOG.isDebugEnabled()) {
-			LOG.debug("AbstractPreAuthenticatedProcessingFilter: preAuthenticatedPrincipal=" + principal + ", trying to authenticate");
-		}
-
-		try {
-			PreAuthenticatedAuthenticationToken authRequest = new PreAuthenticatedAuthenticationToken(principal, credentials);
-			authRequest.setDetails(authenticationDetailsSource.buildDetails(httpRequest));
-			authResult = authenticationManager.authenticate(authRequest);
-			successfulAuthentication(httpRequest, httpResponse, authResult);
-		} catch (AuthenticationException failed) {
-			unsuccessfulAuthentication(httpRequest, httpResponse, failed);
-		}
-	}
-
-	/**
-	 * Puts the <code>Authentication</code> instance returned by the
-	 * authentication manager into the secure context.
-	 */
-	protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) {
-		if (LOG.isDebugEnabled()) {
-			LOG.debug("Authentication success: " + authResult);
-		}
-		SecurityContextHolder.getContext().setAuthentication(authResult);
-		// Fire event
-		if (this.eventPublisher != null) {
-			eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
-		}
-	}
-
-	/**
-	 * Ensures the authentication object in the secure context is set to null
-	 * when authentication fails.
-	 */
-	protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) {
-		SecurityContextHolder.clearContext();
-
-        if (LOG.isDebugEnabled()) {
-			LOG.debug("Cleared security context due to exception", failed);
-		}
-		request.getSession().setAttribute(AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY, failed);
-	}
-
-	/**
-	 * @param anApplicationEventPublisher
-	 *            The ApplicationEventPublisher to use
-	 */
-	public void setApplicationEventPublisher(ApplicationEventPublisher anApplicationEventPublisher) {
-		this.eventPublisher = anApplicationEventPublisher;
-	}
-
-	/**
-	 * @param authenticationDetailsSource
-	 *            The AuthenticationDetailsSource to use
-	 */
-	public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
-		Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
-		this.authenticationDetailsSource = authenticationDetailsSource;
-	}
-
-	/**
-	 * @param authenticationManager
-	 *            The AuthenticationManager to use
-	 */
-	public void setAuthenticationManager(AuthenticationManager authenticationManager) {
-		this.authenticationManager = authenticationManager;
-	}
-
-	protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest httpRequest);
-
-	protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest httpRequest);
+    protected final Log logger = LogFactory.getLog(getClass());
+
+    private ApplicationEventPublisher eventPublisher = null;
+
+    private AuthenticationDetailsSource authenticationDetailsSource = new AuthenticationDetailsSourceImpl();
+
+    private AuthenticationManager authenticationManager = null;
+
+    /**
+     * Check whether all required properties have been set.
+     */
+    public void afterPropertiesSet() throws Exception {
+        Assert.notNull(authenticationManager, "An AuthenticationManager must be set");
+    }
+
+    /**
+     * Try to authenticate a pre-authenticated user with Spring Security if the user has not yet been authenticated.
+     */
+    public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
+        if (logger.isDebugEnabled()) {
+            logger.debug("Checking secure context token: " + SecurityContextHolder.getContext().getAuthentication());
+        }
+
+        if (SecurityContextHolder.getContext().getAuthentication() == null) {
+            doAuthenticate(request, response);
+        }
+        filterChain.doFilter(request, response);
+    }
+
+    /**
+     * Do the actual authentication for a pre-authenticated user.
+     */
+    private void doAuthenticate(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
+        Authentication authResult = null;
+
+        Object principal = getPreAuthenticatedPrincipal(httpRequest);
+        Object credentials = getPreAuthenticatedCredentials(httpRequest);
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("AbstractPreAuthenticatedProcessingFilter: preAuthenticatedPrincipal=" + principal + ", trying to authenticate");
+        }
+
+        try {
+            PreAuthenticatedAuthenticationToken authRequest = new PreAuthenticatedAuthenticationToken(principal, credentials);
+            authRequest.setDetails(authenticationDetailsSource.buildDetails(httpRequest));
+            authResult = authenticationManager.authenticate(authRequest);
+            successfulAuthentication(httpRequest, httpResponse, authResult);
+        } catch (AuthenticationException failed) {
+            unsuccessfulAuthentication(httpRequest, httpResponse, failed);
+        }
+    }
+
+    /**
+     * Puts the <code>Authentication</code> instance returned by the
+     * authentication manager into the secure context.
+     */
+    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) {
+        if (logger.isDebugEnabled()) {
+            logger.debug("Authentication success: " + authResult);
+        }
+        SecurityContextHolder.getContext().setAuthentication(authResult);
+        // Fire event
+        if (this.eventPublisher != null) {
+            eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
+        }
+    }
+
+    /**
+     * Ensures the authentication object in the secure context is set to null
+     * when authentication fails.
+     */
+    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) {
+        SecurityContextHolder.clearContext();
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("Cleared security context due to exception", failed);
+        }
+        request.getSession().setAttribute(AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY, failed);
+    }
+
+    /**
+     * @param anApplicationEventPublisher
+     *            The ApplicationEventPublisher to use
+     */
+    public void setApplicationEventPublisher(ApplicationEventPublisher anApplicationEventPublisher) {
+        this.eventPublisher = anApplicationEventPublisher;
+    }
+
+    /**
+     * @param authenticationDetailsSource
+     *            The AuthenticationDetailsSource to use
+     */
+    public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
+        Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
+        this.authenticationDetailsSource = authenticationDetailsSource;
+    }
+
+    /**
+     * @param authenticationManager
+     *            The AuthenticationManager to use
+     */
+    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
+        this.authenticationManager = authenticationManager;
+    }
+
+    protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest httpRequest);
+
+    protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest httpRequest);
 }

+ 5 - 2
core/src/main/java/org/springframework/security/ui/preauth/PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.java

@@ -13,6 +13,9 @@ import org.springframework.util.Assert;
 /**
  * This WebAuthenticationDetails implementation allows for storing a list of
  * pre-authenticated Granted Authorities.
+ *
+ * @author Ruud Senden
+ * @since 2.0
  */
 public class PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails extends WebAuthenticationDetails implements
 		PreAuthenticatedGrantedAuthoritiesRetriever, PreAuthenticatedGrantedAuthoritiesSetter {
@@ -36,7 +39,7 @@ public class PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails extends
 
 	/*
 	 * (non-Javadoc)
-	 * 
+	 *
 	 * @see org.springframework.security.providers.preauth.PreAuthenticatedGrantedAuthoritiesRetriever#getPreAuthenticatedGrantedAuthorities()
 	 */
 	public GrantedAuthority[] getPreAuthenticatedGrantedAuthorities() {
@@ -48,7 +51,7 @@ public class PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails extends
 
 	/*
 	 * (non-Javadoc)
-	 * 
+	 *
 	 * @see org.springframework.security.providers.preauth.j2ee.PreAuthenticatedGrantedAuthoritiesSetter#setJ2eeBasedGrantedAuthorities()
 	 */
 	public void setPreAuthenticatedGrantedAuthorities(GrantedAuthority[] aJ2eeBasedGrantedAuthorities) {

+ 9 - 9
core/src/main/java/org/springframework/security/ui/preauth/PreAuthenticatedProcesingFilterEntryPoint.java → core/src/main/java/org/springframework/security/ui/preauth/PreAuthenticatedProcessingFilterEntryPoint.java

@@ -20,26 +20,26 @@ import org.springframework.core.Ordered;
  * user will already have been identified through some external mechanism and a
  * secure context established by the time the security-enforcement filter is
  * invoked.
- * </p>
  * <p>
  * Therefore this class isn't actually responsible for the commencement of
  * authentication, as it is in the case of other providers. It will be called if
  * the user is rejected by the AbstractPreAuthenticatedProcessingFilter,
  * resulting in a null authentication.
- * </p>
  * <p>
  * The <code>commence</code> method will always return an
  * <code>HttpServletResponse.SC_FORBIDDEN</code> (403 error).
- * </p>
  * <p>
  * This code is based on
  * {@link org.springframework.security.ui.x509.X509ProcessingFilterEntryPoint}.
- * </p>
- * 
+ *
  * @see org.springframework.security.ui.ExceptionTranslationFilter
+ *
+ * @author Luke Taylor
+ * @author Ruud Senden
+ * @since 2.0
  */
-public class PreAuthenticatedProcesingFilterEntryPoint implements AuthenticationEntryPoint, Ordered {
-	private static final Log LOG = LogFactory.getLog(PreAuthenticatedProcesingFilterEntryPoint.class);
+public class PreAuthenticatedProcessingFilterEntryPoint implements AuthenticationEntryPoint, Ordered {
+	private static final Log logger = LogFactory.getLog(PreAuthenticatedProcessingFilterEntryPoint.class);
 
 	private int order = Integer.MAX_VALUE;
 
@@ -48,8 +48,8 @@ public class PreAuthenticatedProcesingFilterEntryPoint implements Authentication
 	 */
 	public void commence(ServletRequest request, ServletResponse response, AuthenticationException arg2) throws IOException,
 			ServletException {
-		if (LOG.isDebugEnabled()) {
-			LOG.debug("J2EE entry point called. Rejecting access");
+		if (logger.isDebugEnabled()) {
+			logger.debug("Pre-authenticated entry point called. Rejecting access");
 		}
 		HttpServletResponse httpResponse = (HttpServletResponse) response;
 		httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");

+ 70 - 70
core/src/main/java/org/springframework/security/ui/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.java

@@ -18,84 +18,84 @@ import org.springframework.beans.factory.InitializingBean;
 import org.springframework.util.Assert;
 
 public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource extends AuthenticationDetailsSourceImpl implements InitializingBean {
-	private static final Log LOG = LogFactory.getLog(J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.class);
+    private static final Log logger = LogFactory.getLog(J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.class);
 
-	private String[] j2eeMappableRoles;
+    private String[] j2eeMappableRoles;
 
-	private Roles2GrantedAuthoritiesMapper j2eeUserRoles2GrantedAuthoritiesMapper;
+    private Roles2GrantedAuthoritiesMapper j2eeUserRoles2GrantedAuthoritiesMapper;
 
-	/**
-	 * Public constructor which overrides the default AuthenticationDetails
-	 * class to be used.
-	 */
-	public J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource() {
-		super.setClazz(PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.class);
-	}
+    /**
+     * Public constructor which overrides the default AuthenticationDetails
+     * class to be used.
+     */
+    public J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource() {
+        super.setClazz(PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.class);
+    }
 
-	/**
-	 * Check that all required properties have been set.
-	 */
-	public void afterPropertiesSet() throws Exception {
-		Assert.notNull(j2eeMappableRoles, "J2EE defined roles not available");
-		Assert.notNull(j2eeUserRoles2GrantedAuthoritiesMapper, "J2EE user roles to granted authorities mapper not set");
-	}
+    /**
+     * Check that all required properties have been set.
+     */
+    public void afterPropertiesSet() throws Exception {
+        Assert.notNull(j2eeMappableRoles, "J2EE defined roles not available");
+        Assert.notNull(j2eeUserRoles2GrantedAuthoritiesMapper, "J2EE user roles to granted authorities mapper not set");
+    }
 
-	/**
-	 * Build the authentication details object. If the speficied authentication
-	 * details class implements the PreAuthenticatedGrantedAuthoritiesSetter, a
-	 * list of pre-authenticated Granted Authorities will be set based on the
-	 * J2EE roles for the current user.
-	 * 
-	 * @see org.springframework.security.ui.AuthenticationDetailsSource#buildDetails(javax.servlet.http.HttpServletRequest)
-	 */
-	public Object buildDetails(HttpServletRequest request) {
-		Object result = super.buildDetails(request);
-		if (result instanceof PreAuthenticatedGrantedAuthoritiesSetter) {
-			((PreAuthenticatedGrantedAuthoritiesSetter) result)
-					.setPreAuthenticatedGrantedAuthorities(getJ2eeBasedGrantedAuthorities(request));
-		}
-		return result;
-	}
+    /**
+     * Build the authentication details object. If the speficied authentication
+     * details class implements the PreAuthenticatedGrantedAuthoritiesSetter, a
+     * list of pre-authenticated Granted Authorities will be set based on the
+     * J2EE roles for the current user.
+     *
+     * @see org.springframework.security.ui.AuthenticationDetailsSource#buildDetails(javax.servlet.http.HttpServletRequest)
+     */
+    public Object buildDetails(HttpServletRequest request) {
+        Object result = super.buildDetails(request);
+        if (result instanceof PreAuthenticatedGrantedAuthoritiesSetter) {
+            ((PreAuthenticatedGrantedAuthoritiesSetter) result)
+                    .setPreAuthenticatedGrantedAuthorities(getJ2eeBasedGrantedAuthorities(request));
+        }
+        return result;
+    }
 
-	/**
-	 * Get a list of Granted Authorities based on the current user's J2EE roles.
-	 * 
-	 * @param request
-	 *            The HttpServletRequest
-	 * @return GrantedAuthority[] mapped from the user's J2EE roles.
-	 */
-	private GrantedAuthority[] getJ2eeBasedGrantedAuthorities(HttpServletRequest request) {
-		ArrayList j2eeUserRolesList = new ArrayList();
+    /**
+     * Get a list of Granted Authorities based on the current user's J2EE roles.
+     *
+     * @param request
+     *            The HttpServletRequest
+     * @return GrantedAuthority[] mapped from the user's J2EE roles.
+     */
+    private GrantedAuthority[] getJ2eeBasedGrantedAuthorities(HttpServletRequest request) {
+        ArrayList j2eeUserRolesList = new ArrayList();
 
-		for (int i = 0; i < j2eeMappableRoles.length; i++) {
-			if (request.isUserInRole(j2eeMappableRoles[i])) {
-				j2eeUserRolesList.add(j2eeMappableRoles[i]);
-			}
-		}
-		String[] j2eeUserRoles = new String[j2eeUserRolesList.size()];
-		j2eeUserRoles = (String[]) j2eeUserRolesList.toArray(j2eeUserRoles);
-		GrantedAuthority[] userGas = j2eeUserRoles2GrantedAuthoritiesMapper.getGrantedAuthorities(j2eeUserRoles);
-		if (LOG.isDebugEnabled()) {
-			LOG.debug("J2EE user roles [" + StringUtils.join(j2eeUserRoles) + "] mapped to Granted Authorities: ["
-					+ StringUtils.join(userGas) + "]");
-		}
-		return userGas;
-	}
+        for (int i = 0; i < j2eeMappableRoles.length; i++) {
+            if (request.isUserInRole(j2eeMappableRoles[i])) {
+                j2eeUserRolesList.add(j2eeMappableRoles[i]);
+            }
+        }
+        String[] j2eeUserRoles = new String[j2eeUserRolesList.size()];
+        j2eeUserRoles = (String[]) j2eeUserRolesList.toArray(j2eeUserRoles);
+        GrantedAuthority[] userGas = j2eeUserRoles2GrantedAuthoritiesMapper.getGrantedAuthorities(j2eeUserRoles);
+        if (logger.isDebugEnabled()) {
+            logger.debug("J2EE user roles [" + StringUtils.join(j2eeUserRoles) + "] mapped to Granted Authorities: ["
+                    + StringUtils.join(userGas) + "]");
+        }
+        return userGas;
+    }
 
-	/**
-	 * @param aJ2eeMappableRolesRetriever
-	 *            The MappableRolesRetriever to use
-	 */
-	public void setJ2eeMappableRolesRetriever(MappableRolesRetriever aJ2eeMappableRolesRetriever) {
-		this.j2eeMappableRoles = aJ2eeMappableRolesRetriever.getMappableRoles();
-	}
+    /**
+     * @param aJ2eeMappableRolesRetriever
+     *            The MappableRolesRetriever to use
+     */
+    public void setJ2eeMappableRolesRetriever(MappableRolesRetriever aJ2eeMappableRolesRetriever) {
+        this.j2eeMappableRoles = aJ2eeMappableRolesRetriever.getMappableRoles();
+    }
 
-	/**
-	 * @param mapper
-	 *            The Roles2GrantedAuthoritiesMapper to use
-	 */
-	public void setJ2eeUserRoles2GrantedAuthoritiesMapper(Roles2GrantedAuthoritiesMapper mapper) {
-		j2eeUserRoles2GrantedAuthoritiesMapper = mapper;
-	}
+    /**
+     * @param mapper
+     *            The Roles2GrantedAuthoritiesMapper to use
+     */
+    public void setJ2eeUserRoles2GrantedAuthoritiesMapper(Roles2GrantedAuthoritiesMapper mapper) {
+        j2eeUserRoles2GrantedAuthoritiesMapper = mapper;
+    }
 
 }

+ 21 - 22
core/src/main/java/org/springframework/security/ui/preauth/j2ee/J2eePreAuthenticatedProcessingFilter.java

@@ -3,36 +3,35 @@ package org.springframework.security.ui.preauth.j2ee;
 import javax.servlet.http.HttpServletRequest;
 
 import org.springframework.security.ui.preauth.AbstractPreAuthenticatedProcessingFilter;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 
 /**
  * This AbstractPreAuthenticatedProcessingFilter implementation is based on the
  * J2EE container-based authentication mechanism. It will use the J2EE user
  * principal name as the pre-authenticated principal.
+ *
+ * @author Ruud Senden
+ * @since 2.0
  */
 public class J2eePreAuthenticatedProcessingFilter extends AbstractPreAuthenticatedProcessingFilter {
-	private static final Log LOG = LogFactory.getLog(J2eePreAuthenticatedProcessingFilter.class);
-
-	/**
-	 * Return the J2EE user name.
-	 */
-	protected Object getPreAuthenticatedPrincipal(HttpServletRequest httpRequest) {
-		Object principal = httpRequest.getUserPrincipal() == null ? null : httpRequest.getUserPrincipal().getName();
-		if (LOG.isDebugEnabled()) {
-			LOG.debug("PreAuthenticated J2EE principal: " + principal);
-		}
-		return principal;
-	}
+    /**
+     * Return the J2EE user name.
+     */
+    protected Object getPreAuthenticatedPrincipal(HttpServletRequest httpRequest) {
+        Object principal = httpRequest.getUserPrincipal() == null ? null : httpRequest.getUserPrincipal().getName();
+        if (logger.isDebugEnabled()) {
+            logger.debug("PreAuthenticated J2EE principal: " + principal);
+        }
+        return principal;
+    }
 
-	/**
-	 * For J2EE container-based authentication there is no generic way to
-	 * retrieve the credentials, as such this method returns a fixed dummy
-	 * value.
-	 */
-	protected Object getPreAuthenticatedCredentials(HttpServletRequest httpRequest) {
-		return "N/A";
-	}
+    /**
+     * For J2EE container-based authentication there is no generic way to
+     * retrieve the credentials, as such this method returns a fixed dummy
+     * value.
+     */
+    protected Object getPreAuthenticatedCredentials(HttpServletRequest httpRequest) {
+        return "N/A";
+    }
 
     public int getOrder() {
         return 0;

+ 29 - 31
core/src/main/java/org/springframework/security/ui/preauth/j2ee/WebXmlMappableRolesRetriever.java

@@ -9,44 +9,42 @@ import org.springframework.security.rolemapping.XmlMappableRolesRetriever;
  * This MappableRolesRetriever implementation reads the list of defined J2EE
  * roles from a web.xml file. It's functionality is based on the
  * XmlMappableRolesRetriever base class.
- * </p>
- * 
  * <p>
  * Example on how to configure this MappableRolesRetriever in the Spring
  * configuration file:
- * 
+ *
  * <pre>
- * 
- *  
- *   	&lt;bean id=&quot;j2eeMappableRolesRetriever&quot; class=&quot;org.springframework.security.ui.preauth.j2ee.WebXmlMappableRolesRetriever&quot;&gt;
- *  		&lt;property name=&quot;webXmlInputStream&quot;&gt;&lt;bean factory-bean=&quot;webXmlResource&quot; factory-method=&quot;getInputStream&quot;/&gt;&lt;/property&gt;
- *  	&lt;/bean&gt;
- *  	&lt;bean id=&quot;webXmlResource&quot; class=&quot;org.springframework.web.context.support.ServletContextResource&quot;&gt;
- *  		&lt;constructor-arg&gt;&lt;ref local=&quot;servletContext&quot;/&gt;&lt;/constructor-arg&gt;
- *  		&lt;constructor-arg&gt;&lt;value&gt;/WEB-INF/web.xml&lt;/value&gt;&lt;/constructor-arg&gt;
- *  	&lt;/bean&gt;
- *  	&lt;bean id=&quot;servletContext&quot; class=&quot;org.springframework.web.context.support.ServletContextFactoryBean&quot;/&gt;
- *   
- *  
+ *
+ *
+ * &lt;bean id=&quot;j2eeMappableRolesRetriever&quot; class=&quot;org.springframework.security.ui.preauth.j2ee.WebXmlMappableRolesRetriever&quot;&gt;
+ *     &lt;property name=&quot;webXmlInputStream&quot;&gt;&lt;bean factory-bean=&quot;webXmlResource&quot; factory-method=&quot;getInputStream&quot;/&gt;&lt;/property&gt;
+ * &lt;/bean&gt;
+ * &lt;bean id=&quot;webXmlResource&quot; class=&quot;org.springframework.web.context.support.ServletContextResource&quot;&gt;
+ *     &lt;constructor-arg&gt;&lt;ref local=&quot;servletContext&quot;/&gt;&lt;/constructor-arg&gt;
+ *     &lt;constructor-arg&gt;&lt;value&gt;/WEB-INF/web.xml&lt;/value&gt;&lt;/constructor-arg&gt;
+ * &lt;/bean&gt;
+ * &lt;bean id=&quot;servletContext&quot; class=&quot;org.springframework.web.context.support.ServletContextFactoryBean&quot;/&gt;
+ *
  * </pre>
- * 
- * </p>
+ *
+ * @author Ruud Senden
+ * @since 2.0
  */
 public class WebXmlMappableRolesRetriever extends XmlMappableRolesRetriever {
-	private static final String XPATH_EXPR = "/web-app/security-role/role-name/text()";
+    private static final String XPATH_EXPR = "/web-app/security-role/role-name/text()";
 
-	/**
-	 * Constructor setting the XPath expression to use
-	 */
-	public WebXmlMappableRolesRetriever() {
-		super.setXpathExpression(XPATH_EXPR);
-	}
+    /**
+     * Constructor setting the XPath expression to use
+     */
+    public WebXmlMappableRolesRetriever() {
+        super.setXpathExpression(XPATH_EXPR);
+    }
 
-	/**
-	 * @param anInputStream
-	 *            The InputStream to read the XML data from
-	 */
-	public void setWebXmlInputStream(InputStream anInputStream) {
-		super.setXmlInputStream(anInputStream);
-	}
+    /**
+     * @param anInputStream
+     *            The InputStream to read the XML data from
+     */
+    public void setWebXmlInputStream(InputStream anInputStream) {
+        super.setXmlInputStream(anInputStream);
+    }
 }

+ 5 - 5
core/src/test/java/org/springframework/security/ui/preauth/PreAuthenticatedProcesingFilterEntryPointTests.java

@@ -13,22 +13,22 @@ import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.mock.web.MockHttpServletResponse;
 
 /**
- * 
+ *
  * @author TSARDD
  * @since 18-okt-2007
  */
 public class PreAuthenticatedProcesingFilterEntryPointTests extends TestCase {
 
 	public void testGetSetOrder() {
-		PreAuthenticatedProcesingFilterEntryPoint fep = new PreAuthenticatedProcesingFilterEntryPoint();
+		PreAuthenticatedProcessingFilterEntryPoint fep = new PreAuthenticatedProcessingFilterEntryPoint();
 		fep.setOrder(333);
 		assertEquals(fep.getOrder(), 333);
 	}
-	
+
 	public void testCommence() {
 		MockHttpServletRequest req = new MockHttpServletRequest();
 		MockHttpServletResponse resp = new MockHttpServletResponse();
-		PreAuthenticatedProcesingFilterEntryPoint fep = new PreAuthenticatedProcesingFilterEntryPoint();
+		PreAuthenticatedProcessingFilterEntryPoint fep = new PreAuthenticatedProcessingFilterEntryPoint();
 		try {
 			fep.commence(req,resp,new AuthenticationCredentialsNotFoundException("test"));
 			assertEquals("Incorrect status",resp.getStatus(),HttpServletResponse.SC_FORBIDDEN);
@@ -37,6 +37,6 @@ public class PreAuthenticatedProcesingFilterEntryPointTests extends TestCase {
 		} catch (ServletException e) {
 			fail("Unexpected exception thrown: "+e);
 		}
-		
+
 	}
 }

+ 116 - 0
samples/preauth/pom.xml

@@ -0,0 +1,116 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.security</groupId>
+        <artifactId>spring-security-samples</artifactId>
+        <version>2.0-SNAPSHOT</version>
+    </parent>
+    <groupId>org.springframework.security</groupId>
+    <artifactId>spring-security-samples-preauth</artifactId>
+    <name>Spring Security - Preauthentiation sample</name>
+    <packaging>war</packaging>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-core-tiger</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webmvc</artifactId>
+	        <version>${spring.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-jdbc</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-aop</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>jstl</artifactId>
+            <version>1.2</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>taglibs</groupId>
+            <artifactId>standard</artifactId>
+            <version>1.0.6</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>jaxen</groupId>
+            <artifactId>jaxen</artifactId>
+            <version>1.1.1</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.directory.server</groupId>
+            <artifactId>apacheds-core</artifactId>
+            <version>1.0.2</version>
+            <scope>compile</scope>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.directory.server</groupId>
+            <artifactId>apacheds-server-jndi</artifactId>
+            <version>1.0.2</version>
+            <scope>compile</scope>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <version>1.4.3</version>
+            <scope>runtime</scope>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.ldap</groupId>
+            <artifactId>spring-ldap</artifactId>
+            <version>1.2.1</version>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>1.5</source>
+          <target>1.5</target>
+        </configuration>
+      </plugin>
+            <plugin>
+                <groupId>org.mortbay.jetty</groupId>
+                <artifactId>maven-jetty-plugin</artifactId>
+                <version>6.1.5</version>
+                <configuration>
+                    <contextPath>/preauth</contextPath>
+                    <userRealms>
+                        <userRealm implementation="org.mortbay.jetty.security.HashUserRealm">
+                            <name>Preauth Realm</name>
+                            <config>realm.properties</config>
+                        </userRealm>
+                    </userRealms>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 3 - 0
samples/preauth/realm.properties

@@ -0,0 +1,3 @@
+rod: koala,ROLE_SUPERVISOR,ROLE_USER
+bob: bobspassword,ROLE_USER
+user: password

+ 125 - 0
samples/preauth/src/main/webapp/WEB-INF/applicationContext-security.xml

@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  - Sample namespace-based configuration
+  -
+  - $Id: applicationContext-security-ns.xml 2396 2007-12-23 16:36:44Z luke_t $
+  -->
+
+<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="filterChainProxy" class="org.springframework.security.util.FilterChainProxy">
+        <filter-chain-map path-type="ant">
+            <filter-chain pattern="/**" filters="sif,j2eePreAuthFilter,logoutFilter,etf,fsi"/>
+        </filter-chain-map>
+    </b:bean>
+
+
+    <b:bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
+        <b:property name="providers">
+        <b:list>
+            <b:ref local="preAuthenticatedAuthenticationProvider"/>
+        </b:list>
+        </b:property>
+    </b:bean>
+
+    <b:bean id="sif" class="org.springframework.security.context.HttpSessionContextIntegrationFilter"/>
+
+    <b:bean id="preAuthenticatedAuthenticationProvider" class="org.springframework.security.providers.preauth.PreAuthenticatedAuthenticationProvider">
+        <b:property name="preAuthenticatedUserDetailsService" ref="preAuthenticatedUserDetailsService"/>
+    </b:bean>
+
+    <b:bean id="preAuthenticatedUserDetailsService"
+            class="org.springframework.security.providers.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService"/>
+
+    <b:bean id="j2eePreAuthFilter" class="org.springframework.security.ui.preauth.j2ee.J2eePreAuthenticatedProcessingFilter">
+        <b:property name="authenticationManager" ref="authenticationManager"/>
+        <b:property name="authenticationDetailsSource" ref="authenticationDetailsSource"/>
+    </b:bean>
+
+    <b:bean id="preAuthenticatedProcessingFilterEntryPoint"
+            class="org.springframework.security.ui.preauth.PreAuthenticatedProcessingFilterEntryPoint"/>
+
+
+	<b:bean id="logoutFilter" class="org.springframework.security.ui.logout.LogoutFilter">
+		<b:constructor-arg value="/"/>
+		<b:constructor-arg>
+			<b:list>
+				<b:bean class="org.springframework.security.ui.logout.SecurityContextLogoutHandler"/>
+			</b:list>
+		</b:constructor-arg>
+	</b:bean>
+
+    <b:bean id="authenticationDetailsSource" class="org.springframework.security.ui.preauth.j2ee.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource">
+        <b:property name="j2eeMappableRolesRetriever">
+        <b:ref local="j2eeMappableRolesRetriever"/>
+        </b:property>
+
+            <b:property name="j2eeUserRoles2GrantedAuthoritiesMapper">
+        <b:ref local="j2eeUserRoles2GrantedAuthoritiesMapper"/>
+        </b:property>
+    </b:bean>
+
+	<b:bean id="j2eeUserRoles2GrantedAuthoritiesMapper" class="org.springframework.security.rolemapping.SimpleRoles2GrantedAuthoritiesMapper">
+	    <b:property name="convertRoleToUpperCase" value="true"/>
+    </b:bean>
+
+	<b:bean id="j2eeMappableRolesRetriever" class="org.springframework.security.ui.preauth.j2ee.WebXmlMappableRolesRetriever">
+
+	<b:property name="webXmlInputStream"><b:bean factory-bean="webXmlResource" factory-method="getInputStream"/>
+    </b:property>
+    </b:bean>
+
+	<b:bean id="webXmlResource" class="org.springframework.web.context.support.ServletContextResource">
+        <b:constructor-arg ref="servletContext"/>
+        <b:constructor-arg value="/WEB-INF/web.xml"/>
+    </b:bean>
+
+    <b:bean id="servletContext" class="org.springframework.web.context.support.ServletContextFactoryBean"/>
+
+    <b:bean id="etf" class="org.springframework.security.ui.ExceptionTranslationFilter">
+        <b:property name="authenticationEntryPoint">
+            <b:ref local="preAuthenticatedProcessingFilterEntryPoint"/>
+        </b:property>
+    </b:bean>
+
+	<b:bean id="httpRequestAccessDecisionManager" class="org.springframework.security.vote.AffirmativeBased">
+
+	<b:property name="allowIfAllAbstainDecisions" value="false"/>
+	<b:property name="decisionVoters">
+	    <b:list>
+            <b:ref bean="roleVoter"/>
+        </b:list>
+    </b:property>
+    </b:bean>
+
+
+	<b:bean id="fsi" class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
+	    <b:property name="authenticationManager" ref="authenticationManager"/>
+	    <b:property name="accessDecisionManager">
+        <b:ref local="httpRequestAccessDecisionManager"/>
+    </b:property>
+
+	<b:property name="objectDefinitionSource">
+	    <b:value>
+            CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
+            PATTERN_TYPE_APACHE_ANT
+            /secure/extreme/**=ROLE_SUPERVISOR
+            /secure/**=ROLE_USER
+            /**=ROLE_USER
+        </b:value>
+    </b:property>
+    </b:bean>
+
+    <b:bean id="roleVoter" class="org.springframework.security.vote.RoleVoter"/>
+
+	<b:bean id="securityContextHolderAwareRequestFilter" class="org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter">
+        <b:property name="wrapperClass" value="org.springframework.security.wrapper.SecurityContextHolderAwareRequestWrapper"/>
+    </b:bean>
+
+</b:beans>

+ 20 - 0
samples/preauth/src/main/webapp/WEB-INF/classes/log4j.properties

@@ -0,0 +1,20 @@
+# Global logging configuration
+log4j.rootLogger=INFO, stdout, fileout
+
+log4j.logger.org.springframework.security=DEBUG, stdout, fileout
+
+# Console output...
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.conversionPattern=[%p,%c{1},%t] %m%n
+
+# Rolling log file output...
+log4j.appender.fileout=org.apache.log4j.RollingFileAppender
+log4j.appender.fileout.File=spring-security-preauth.log
+#log4j.appender.fileout.File=${webapp.root}/WEB-INF/log4j.log
+log4j.appender.fileout.MaxFileSize=1024KB
+log4j.appender.fileout.MaxBackupIndex=1
+log4j.appender.fileout.layout=org.apache.log4j.PatternLayout
+log4j.appender.fileout.layout.conversionPattern=%d{ABSOLUTE} %5p %c{1},%t:%L - %m%n
+
+

+ 73 - 0
samples/preauth/src/main/webapp/WEB-INF/web.xml

@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  - Tutorial web application
+  -
+  - $Id: web.xml 2476 2008-01-18 18:17:09Z luke_t $
+  -->
+
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
+
+    <display-name>Spring Security Preauthentication Demo Application</display-name>
+
+    <!--
+	  - Location of the XML file that defines the root application context
+	  - Applied by ContextLoaderListener.
+	  -->
+	<context-param>
+		<param-name>contextConfigLocation</param-name>
+		<param-value>
+			/WEB-INF/applicationContext-security.xml
+		</param-value>
+	</context-param>
+
+    <filter>
+        <filter-name>filterChainProxy</filter-name>
+        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
+    </filter>
+
+    <filter-mapping>
+      <filter-name>filterChainProxy</filter-name>
+      <url-pattern>/*</url-pattern>
+    </filter-mapping>
+
+	<!--
+	  - Loads the root application context of this web app at startup.
+	  - The application context is then available via
+	  - WebApplicationContextUtils.getWebApplicationContext(servletContext).
+    -->
+	<listener>
+		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+	</listener>
+
+	<!--
+	  - Publishes events for session creation and destruction through the application
+	  - context. Optional unless concurrent session control is being used.
+      -->
+    <listener>
+      <listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class>
+    </listener>
+
+    <login-config>
+        <auth-method>BASIC</auth-method>
+        <realm-name>Preauth Realm</realm-name>
+    </login-config>
+
+    <security-role>
+        <role-name>ROLE_USER</role-name>
+    </security-role>
+    <security-role>
+        <role-name>ROLE_SUPERVISOR</role-name>
+    </security-role>
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>All areas</web-resource-name>
+            <url-pattern>/*</url-pattern>
+        </web-resource-collection>
+        <auth-constraint>
+            <role-name>ROLE_USER</role-name>
+        </auth-constraint>
+    </security-constraint>
+
+</web-app>

+ 11 - 0
samples/preauth/src/main/webapp/index.jsp

@@ -0,0 +1,11 @@
+<html>
+<body>
+<h1>Home Page</h1>
+<p>Anyone can view this page.</p>
+
+<p>Your principal object is....: <%= request.getUserPrincipal() %></p>
+
+<p><a href="secure/index.jsp">Secure page</a></p>
+<p><a href="secure/extreme/index.jsp">Extremely secure page</a></p>
+</body>
+</html>

+ 15 - 0
samples/preauth/src/main/webapp/secure/extreme/index.jsp

@@ -0,0 +1,15 @@
+<%@ taglib prefix="authz" uri="http://www.springframework.org/security/tags" %>
+
+<html>
+<body>
+<h1>VERY Secure Page</h1>
+This is a protected page. You can only see me if you are a supervisor.
+
+<authz:authorize ifAllGranted="ROLE_SUPERVISOR">
+   You have "ROLE_SUPERVISOR" (this text is surrounded by &lt;authz:authorize&gt; tags).
+</authz:authorize>
+
+<p><a href="../../">Home</a>
+<p><a href="../../j_spring_security_logout">Logout</a>
+</body>
+</html>

+ 15 - 0
samples/preauth/src/main/webapp/secure/index.jsp

@@ -0,0 +1,15 @@
+<html>
+<body>
+<h1>Secure Page</h1>
+This is a protected page. You can get to me if you've been remembered,
+or if you've authenticated this session.<br><br>
+
+<%if (request.isUserInRole("ROLE_SUPERVISOR")) { %>
+	You are a supervisor! You can therefore see the <a href="extreme/index.jsp">extremely secure page</a>.<br><br>
+<% } %>
+
+
+<p><a href="../">Home</a>
+<p><a href="../j_spring_security_logout">Logout</a>
+</body>
+</html>