Browse Source

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

Luke Taylor 17 năm trước cách đây
mục cha
commit
837ecd85ec
27 tập tin đã thay đổi với 1043 bổ sung637 xóa
  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>