From 837ecd85ec02859fad7a0acc45cb91392da539a5 Mon Sep 17 00:00:00 2001 From: Luke Taylor Date: Wed, 23 Jan 2008 20:02:11 +0000 Subject: [PATCH] SEC-576: Tidied up code, added preauth sample demo app. --- ...reAuthenticatedAuthenticationProvider.java | 103 +++---- .../PreAuthenticatedAuthenticationToken.java | 105 +++---- ...henticatedGrantedAuthoritiesRetriever.java | 11 +- ...AuthenticatedGrantedAuthoritiesSetter.java | 13 +- ...dGrantedAuthoritiesUserDetailsService.java | 5 +- .../PreAuthenticatedUserDetailsService.java | 7 +- .../UserDetailsByNameServiceWrapper.java | 9 +- .../rolemapping/MappableRolesRetriever.java | 17 +- .../Roles2GrantedAuthoritiesMapper.java | 26 +- .../SimpleMappableRolesRetriever.java | 35 +-- .../SimpleRoles2GrantedAuthoritiesMapper.java | 136 ++++----- .../XmlMappableRolesRetriever.java | 258 +++++++++--------- ...tractPreAuthenticatedProcessingFilter.java | 181 ++++++------ ...edAuthoritiesWebAuthenticationDetails.java | 7 +- ...henticatedProcessingFilterEntryPoint.java} | 18 +- ...ticatedWebAuthenticationDetailsSource.java | 140 +++++----- .../J2eePreAuthenticatedProcessingFilter.java | 43 ++- .../j2ee/WebXmlMappableRolesRetriever.java | 60 ++-- ...ticatedProcesingFilterEntryPointTests.java | 10 +- samples/preauth/pom.xml | 116 ++++++++ samples/preauth/realm.properties | 3 + .../WEB-INF/applicationContext-security.xml | 125 +++++++++ .../webapp/WEB-INF/classes/log4j.properties | 20 ++ .../preauth/src/main/webapp/WEB-INF/web.xml | 73 +++++ samples/preauth/src/main/webapp/index.jsp | 11 + .../src/main/webapp/secure/extreme/index.jsp | 15 + .../preauth/src/main/webapp/secure/index.jsp | 15 + 27 files changed, 984 insertions(+), 578 deletions(-) rename core/src/main/java/org/springframework/security/ui/preauth/{PreAuthenticatedProcesingFilterEntryPoint.java => PreAuthenticatedProcessingFilterEntryPoint.java} (80%) create mode 100644 samples/preauth/pom.xml create mode 100644 samples/preauth/realm.properties create mode 100644 samples/preauth/src/main/webapp/WEB-INF/applicationContext-security.xml create mode 100644 samples/preauth/src/main/webapp/WEB-INF/classes/log4j.properties create mode 100644 samples/preauth/src/main/webapp/WEB-INF/web.xml create mode 100644 samples/preauth/src/main/webapp/index.jsp create mode 100644 samples/preauth/src/main/webapp/secure/extreme/index.jsp create mode 100644 samples/preauth/src/main/webapp/secure/index.jsp diff --git a/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedAuthenticationProvider.java b/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedAuthenticationProvider.java index 9300af47da..748429aaee 100755 --- a/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedAuthenticationProvider.java +++ b/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. - *

- * + * *

* 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. - *

+ * + * @author Ruud Senden + * @since 2.0 */ public class PreAuthenticatedAuthenticationProvider implements AuthenticationProvider, InitializingBean, Ordered { - private static final Log LOG = LogFactory.getLog(PreAuthenticatedAuthenticationProvider.class); + private static final Log logger = LogFactory.getLog(PreAuthenticatedAuthenticationProvider.class); - private PreAuthenticatedUserDetailsService preAuthenticatedUserDetailsService = null; + private PreAuthenticatedUserDetailsService preAuthenticatedUserDetailsService = null; - private int order = -1; // default: same as non-ordered + 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"); - } + /** + * 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; - } + /** + * 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); - } + if (logger.isDebugEnabled()) { + logger.debug("PreAuthenticated authentication request: " + authentication); + } - UserDetails ud = preAuthenticatedUserDetailsService.getUserDetails((PreAuthenticatedAuthenticationToken) authentication); - if (ud == null) { - return null; - } - PreAuthenticatedAuthenticationToken result = + UserDetails ud = preAuthenticatedUserDetailsService.getUserDetails((PreAuthenticatedAuthenticationToken) authentication); + + if (ud == null) { + return null; + } + + PreAuthenticatedAuthenticationToken result = new PreAuthenticatedAuthenticationToken(ud, authentication.getCredentials(), ud.getAuthorities()); - result.setDetails(authentication.getDetails()); + result.setDetails(authentication.getDetails()); - return result; + return result; - } + } - /** - * Indicate that this provider only supports PreAuthenticatedAuthenticationToken (sub)classes. - */ - public boolean supports(Class authentication) { - return PreAuthenticatedAuthenticationToken.class.isAssignableFrom(authentication); - } + /** + * 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; - } + /** + * Set the PreAuthenticatedUserDetailsServices to be used. + * + * @param aPreAuthenticatedUserDetailsService + */ + public void setPreAuthenticatedUserDetailsService(PreAuthenticatedUserDetailsService aPreAuthenticatedUserDetailsService) { + this.preAuthenticatedUserDetailsService = aPreAuthenticatedUserDetailsService; + } - public int getOrder() { - return order; - } + public int getOrder() { + return order; + } - public void setOrder(int i) { - order = i; - } + public void setOrder(int i) { + order = i; + } } diff --git a/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedAuthenticationToken.java b/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedAuthenticationToken.java index 4bffbedf63..0936adc701 100755 --- a/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedAuthenticationToken.java +++ b/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 + * false. + * + * @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 - * false. - * - * @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 + * true. + * + * @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 - * true. - * - * @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; + } } diff --git a/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedGrantedAuthoritiesRetriever.java b/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedGrantedAuthoritiesRetriever.java index 4410dda924..c78f090bc0 100755 --- a/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedGrantedAuthoritiesRetriever.java +++ b/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(); } diff --git a/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedGrantedAuthoritiesSetter.java b/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedGrantedAuthoritiesSetter.java index b889ccfc6a..179d81f730 100755 --- a/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedGrantedAuthoritiesSetter.java +++ b/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); } diff --git a/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedGrantedAuthoritiesUserDetailsService.java b/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedGrantedAuthoritiesUserDetailsService.java index 293c6b6c24..314dd604d1 100755 --- a/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedGrantedAuthoritiesUserDetailsService.java +++ b/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(). - *

* *

* The details object as returned by * PreAuthenticatedAuthenticationToken.getDetails() must implement the * PreAuthenticatedGrantedAuthoritiesRetriever interface for this implementation * to work. - *

+ * + * @author Ruud Senden + * @since 2.0 */ public class PreAuthenticatedGrantedAuthoritiesUserDetailsService implements PreAuthenticatedUserDetailsService { /** diff --git a/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedUserDetailsService.java b/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedUserDetailsService.java index 4c8a2167ce..f905eca950 100755 --- a/core/src/main/java/org/springframework/security/providers/preauth/PreAuthenticatedUserDetailsService.java +++ b/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; } diff --git a/core/src/main/java/org/springframework/security/providers/preauth/UserDetailsByNameServiceWrapper.java b/core/src/main/java/org/springframework/security/providers/preauth/UserDetailsByNameServiceWrapper.java index c9b23be98a..2dc104e06c 100755 --- a/core/src/main/java/org/springframework/security/providers/preauth/UserDetailsByNameServiceWrapper.java +++ b/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 */ diff --git a/core/src/main/java/org/springframework/security/rolemapping/MappableRolesRetriever.java b/core/src/main/java/org/springframework/security/rolemapping/MappableRolesRetriever.java index c243881983..b5f4dc0670 100755 --- a/core/src/main/java/org/springframework/security/rolemapping/MappableRolesRetriever.java +++ b/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(); } diff --git a/core/src/main/java/org/springframework/security/rolemapping/Roles2GrantedAuthoritiesMapper.java b/core/src/main/java/org/springframework/security/rolemapping/Roles2GrantedAuthoritiesMapper.java index 958cfeecac..1ccbfa233f 100755 --- a/core/src/main/java/org/springframework/security/rolemapping/Roles2GrantedAuthoritiesMapper.java +++ b/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); } diff --git a/core/src/main/java/org/springframework/security/rolemapping/SimpleMappableRolesRetriever.java b/core/src/main/java/org/springframework/security/rolemapping/SimpleMappableRolesRetriever.java index 6b51f69c6f..0fb26d8c70 100755 --- a/core/src/main/java/org/springframework/security/rolemapping/SimpleMappableRolesRetriever.java +++ b/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); + } } diff --git a/core/src/main/java/org/springframework/security/rolemapping/SimpleRoles2GrantedAuthoritiesMapper.java b/core/src/main/java/org/springframework/security/rolemapping/SimpleRoles2GrantedAuthoritiesMapper.java index 6619662c58..302ecb68ea 100755 --- a/core/src/main/java/org/springframework/security/rolemapping/SimpleRoles2GrantedAuthoritiesMapper.java +++ b/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. - *

- * *

* By default, the role is prefixed with "ROLE_" unless it already starts with * "ROLE_", and no case conversion is done. - *

+ * + * @author Ruud Senden + * @since 2.0 */ public class SimpleRoles2GrantedAuthoritiesMapper implements Roles2GrantedAuthoritiesMapper, InitializingBean { - private String rolePrefix = "ROLE_"; + private String rolePrefix = "ROLE_"; - private boolean convertRoleToUpperCase = false; + private boolean convertRoleToUpperCase = false; - private boolean convertRoleToLowerCase = false; + private boolean convertRoleToLowerCase = false; - private boolean addPrefixIfAlreadyExisting = 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"); - } + /** + * 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 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); - } - } + /** + * 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; - } + private boolean isConvertRoleToLowerCase() { + return convertRoleToLowerCase; + } - public void setConvertRoleToLowerCase(boolean b) { - convertRoleToLowerCase = b; - } + public void setConvertRoleToLowerCase(boolean b) { + convertRoleToLowerCase = b; + } - private boolean isConvertRoleToUpperCase() { - return convertRoleToUpperCase; - } + private boolean isConvertRoleToUpperCase() { + return convertRoleToUpperCase; + } - public void setConvertRoleToUpperCase(boolean b) { - convertRoleToUpperCase = b; - } + public void setConvertRoleToUpperCase(boolean b) { + convertRoleToUpperCase = b; + } - private String getRolePrefix() { - return rolePrefix == null ? "" : rolePrefix; - } + private String getRolePrefix() { + return rolePrefix == null ? "" : rolePrefix; + } - public void setRolePrefix(String string) { - rolePrefix = string; - } + public void setRolePrefix(String string) { + rolePrefix = string; + } - private boolean isAddPrefixIfAlreadyExisting() { - return addPrefixIfAlreadyExisting; - } + private boolean isAddPrefixIfAlreadyExisting() { + return addPrefixIfAlreadyExisting; + } - public void setAddPrefixIfAlreadyExisting(boolean b) { - addPrefixIfAlreadyExisting = b; - } + public void setAddPrefixIfAlreadyExisting(boolean b) { + addPrefixIfAlreadyExisting = b; + } } diff --git a/core/src/main/java/org/springframework/security/rolemapping/XmlMappableRolesRetriever.java b/core/src/main/java/org/springframework/security/rolemapping/XmlMappableRolesRetriever.java index 239dd31566..51eb738193 100755 --- a/core/src/main/java/org/springframework/security/rolemapping/XmlMappableRolesRetriever.java +++ b/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. - * + *

* 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 static final Log LOG = LogFactory.getLog(XmlMappableRolesRetriever.class); - private String[] mappableRoles = null; + private String[] mappableRoles = null; - private InputStream xmlInputStream = null; + private InputStream xmlInputStream = null; - private String xpathExpression = null; + private String xpathExpression = null; - private boolean closeInputStream = true; + 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); - } + /** + * 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; - } + 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); - } - } - } + /** + * 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); + } + } - /** - * @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); + } + } - /** - * @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 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; + } - /** - * 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; + } - /** - * 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("")); + } + } - /** - * 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 static final class IgnoreCloseInputStream extends FilterInputStream { - public IgnoreCloseInputStream(InputStream stream) { - super(stream); - } - - public void close() throws IOException { - // do nothing - } - } + public void close() throws IOException { + // do nothing + } + } } diff --git a/core/src/main/java/org/springframework/security/ui/preauth/AbstractPreAuthenticatedProcessingFilter.java b/core/src/main/java/org/springframework/security/ui/preauth/AbstractPreAuthenticatedProcessingFilter.java index d8fd3ac115..bd6cd62dca 100755 --- a/core/src/main/java/org/springframework/security/ui/preauth/AbstractPreAuthenticatedProcessingFilter.java +++ b/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); + protected final Log logger = LogFactory.getLog(getClass()); - private ApplicationEventPublisher eventPublisher = null; + private ApplicationEventPublisher eventPublisher = null; - private AuthenticationDetailsSource authenticationDetailsSource = new AuthenticationDetailsSourceImpl(); + private AuthenticationDetailsSource authenticationDetailsSource = new AuthenticationDetailsSourceImpl(); - private AuthenticationManager authenticationManager = null; + 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"); - } + /** + * 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()); - } + /** + * 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); - } + 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; + /** + * 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); + Object principal = getPreAuthenticatedPrincipal(httpRequest); + Object credentials = getPreAuthenticatedCredentials(httpRequest); - if (LOG.isDebugEnabled()) { - LOG.debug("AbstractPreAuthenticatedProcessingFilter: preAuthenticatedPrincipal=" + principal + ", trying to authenticate"); - } + 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); - } - } + 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 Authentication 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())); - } - } + /** + * Puts the Authentication 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(); + /** + * 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); - } + 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 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 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; - } + /** + * @param authenticationManager + * The AuthenticationManager to use + */ + public void setAuthenticationManager(AuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + } - protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest httpRequest); + protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest httpRequest); - protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest httpRequest); + protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest httpRequest); } diff --git a/core/src/main/java/org/springframework/security/ui/preauth/PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.java b/core/src/main/java/org/springframework/security/ui/preauth/PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.java index 1827dd8c41..5b8a7a9a1c 100755 --- a/core/src/main/java/org/springframework/security/ui/preauth/PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.java +++ b/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) { diff --git a/core/src/main/java/org/springframework/security/ui/preauth/PreAuthenticatedProcesingFilterEntryPoint.java b/core/src/main/java/org/springframework/security/ui/preauth/PreAuthenticatedProcessingFilterEntryPoint.java similarity index 80% rename from core/src/main/java/org/springframework/security/ui/preauth/PreAuthenticatedProcesingFilterEntryPoint.java rename to core/src/main/java/org/springframework/security/ui/preauth/PreAuthenticatedProcessingFilterEntryPoint.java index cafeb155ac..741376a27b 100755 --- a/core/src/main/java/org/springframework/security/ui/preauth/PreAuthenticatedProcesingFilterEntryPoint.java +++ b/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. - *

*

* 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. - *

*

* The commence method will always return an * HttpServletResponse.SC_FORBIDDEN (403 error). - *

*

* This code is based on * {@link org.springframework.security.ui.x509.X509ProcessingFilterEntryPoint}. - *

- * + * * @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"); diff --git a/core/src/main/java/org/springframework/security/ui/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.java b/core/src/main/java/org/springframework/security/ui/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.java index 1b6f97c624..0af714e0fa 100755 --- a/core/src/main/java/org/springframework/security/ui/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.java +++ b/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; + } } diff --git a/core/src/main/java/org/springframework/security/ui/preauth/j2ee/J2eePreAuthenticatedProcessingFilter.java b/core/src/main/java/org/springframework/security/ui/preauth/j2ee/J2eePreAuthenticatedProcessingFilter.java index 5c433a4af2..7a7d0e5572 100755 --- a/core/src/main/java/org/springframework/security/ui/preauth/j2ee/J2eePreAuthenticatedProcessingFilter.java +++ b/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 (logger.isDebugEnabled()) { + logger.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 (LOG.isDebugEnabled()) { - LOG.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; diff --git a/core/src/main/java/org/springframework/security/ui/preauth/j2ee/WebXmlMappableRolesRetriever.java b/core/src/main/java/org/springframework/security/ui/preauth/j2ee/WebXmlMappableRolesRetriever.java index 1a2d9cb598..754b0f8aa7 100755 --- a/core/src/main/java/org/springframework/security/ui/preauth/j2ee/WebXmlMappableRolesRetriever.java +++ b/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. - *

- * *

* Example on how to configure this MappableRolesRetriever in the Spring * configuration file: - * + * *

- * 
- *  
- *   	<bean id="j2eeMappableRolesRetriever" class="org.springframework.security.ui.preauth.j2ee.WebXmlMappableRolesRetriever">
- *  		<property name="webXmlInputStream"><bean factory-bean="webXmlResource" factory-method="getInputStream"/></property>
- *  	</bean>
- *  	<bean id="webXmlResource" class="org.springframework.web.context.support.ServletContextResource">
- *  		<constructor-arg><ref local="servletContext"/></constructor-arg>
- *  		<constructor-arg><value>/WEB-INF/web.xml</value></constructor-arg>
- *  	</bean>
- *  	<bean id="servletContext" class="org.springframework.web.context.support.ServletContextFactoryBean"/>
- *   
- *  
+ *
+ *
+ * <bean id="j2eeMappableRolesRetriever" class="org.springframework.security.ui.preauth.j2ee.WebXmlMappableRolesRetriever">
+ *     <property name="webXmlInputStream"><bean factory-bean="webXmlResource" factory-method="getInputStream"/></property>
+ * </bean>
+ * <bean id="webXmlResource" class="org.springframework.web.context.support.ServletContextResource">
+ *     <constructor-arg><ref local="servletContext"/></constructor-arg>
+ *     <constructor-arg><value>/WEB-INF/web.xml</value></constructor-arg>
+ * </bean>
+ * <bean id="servletContext" class="org.springframework.web.context.support.ServletContextFactoryBean"/>
+ *
  * 
- * - *

+ * + * @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); + } } diff --git a/core/src/test/java/org/springframework/security/ui/preauth/PreAuthenticatedProcesingFilterEntryPointTests.java b/core/src/test/java/org/springframework/security/ui/preauth/PreAuthenticatedProcesingFilterEntryPointTests.java index d8e3275e5b..74bc580caf 100755 --- a/core/src/test/java/org/springframework/security/ui/preauth/PreAuthenticatedProcesingFilterEntryPointTests.java +++ b/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); } - + } } diff --git a/samples/preauth/pom.xml b/samples/preauth/pom.xml new file mode 100644 index 0000000000..d7607afb33 --- /dev/null +++ b/samples/preauth/pom.xml @@ -0,0 +1,116 @@ + + 4.0.0 + + org.springframework.security + spring-security-samples + 2.0-SNAPSHOT + + org.springframework.security + spring-security-samples-preauth + Spring Security - Preauthentiation sample + war + + + org.springframework.security + spring-security-core + ${project.version} + + + org.springframework.security + spring-security-core-tiger + ${project.version} + + + org.springframework + spring-web + + + org.springframework + spring-webmvc + ${spring.version} + + + org.springframework + spring-jdbc + runtime + + + org.springframework + spring-aop + runtime + + + javax.servlet + jstl + 1.2 + runtime + + + taglibs + standard + 1.0.6 + runtime + + + jaxen + jaxen + 1.1.1 + true + + + org.apache.directory.server + apacheds-core + 1.0.2 + compile + true + + + org.apache.directory.server + apacheds-server-jndi + 1.0.2 + compile + true + + + org.slf4j + slf4j-log4j12 + 1.4.3 + runtime + true + + + org.springframework.ldap + spring-ldap + 1.2.1 + true + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + org.mortbay.jetty + maven-jetty-plugin + 6.1.5 + + /preauth + + + Preauth Realm + realm.properties + + + + + + + + \ No newline at end of file diff --git a/samples/preauth/realm.properties b/samples/preauth/realm.properties new file mode 100644 index 0000000000..91ec2184ec --- /dev/null +++ b/samples/preauth/realm.properties @@ -0,0 +1,3 @@ +rod: koala,ROLE_SUPERVISOR,ROLE_USER +bob: bobspassword,ROLE_USER +user: password \ No newline at end of file diff --git a/samples/preauth/src/main/webapp/WEB-INF/applicationContext-security.xml b/samples/preauth/src/main/webapp/WEB-INF/applicationContext-security.xml new file mode 100644 index 0000000000..e9717dd9f2 --- /dev/null +++ b/samples/preauth/src/main/webapp/WEB-INF/applicationContext-security.xml @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON + PATTERN_TYPE_APACHE_ANT + /secure/extreme/**=ROLE_SUPERVISOR + /secure/**=ROLE_USER + /**=ROLE_USER + + + + + + + + + + + \ No newline at end of file diff --git a/samples/preauth/src/main/webapp/WEB-INF/classes/log4j.properties b/samples/preauth/src/main/webapp/WEB-INF/classes/log4j.properties new file mode 100644 index 0000000000..5a78fdb39c --- /dev/null +++ b/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 + + diff --git a/samples/preauth/src/main/webapp/WEB-INF/web.xml b/samples/preauth/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..f363aa92f3 --- /dev/null +++ b/samples/preauth/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,73 @@ + + + + + + Spring Security Preauthentication Demo Application + + + + contextConfigLocation + + /WEB-INF/applicationContext-security.xml + + + + + filterChainProxy + org.springframework.web.filter.DelegatingFilterProxy + + + + filterChainProxy + /* + + + + + org.springframework.web.context.ContextLoaderListener + + + + + org.springframework.security.ui.session.HttpSessionEventPublisher + + + + BASIC + Preauth Realm + + + + ROLE_USER + + + ROLE_SUPERVISOR + + + + All areas + /* + + + ROLE_USER + + + + diff --git a/samples/preauth/src/main/webapp/index.jsp b/samples/preauth/src/main/webapp/index.jsp new file mode 100644 index 0000000000..9f056599b6 --- /dev/null +++ b/samples/preauth/src/main/webapp/index.jsp @@ -0,0 +1,11 @@ + + +

Home Page

+

Anyone can view this page.

+ +

Your principal object is....: <%= request.getUserPrincipal() %>

+ +

Secure page

+

Extremely secure page

+ + \ No newline at end of file diff --git a/samples/preauth/src/main/webapp/secure/extreme/index.jsp b/samples/preauth/src/main/webapp/secure/extreme/index.jsp new file mode 100644 index 0000000000..93f7a17cfc --- /dev/null +++ b/samples/preauth/src/main/webapp/secure/extreme/index.jsp @@ -0,0 +1,15 @@ +<%@ taglib prefix="authz" uri="http://www.springframework.org/security/tags" %> + + + +

VERY Secure Page

+This is a protected page. You can only see me if you are a supervisor. + + + You have "ROLE_SUPERVISOR" (this text is surrounded by <authz:authorize> tags). + + +

Home +

Logout + + \ No newline at end of file diff --git a/samples/preauth/src/main/webapp/secure/index.jsp b/samples/preauth/src/main/webapp/secure/index.jsp new file mode 100644 index 0000000000..b774c40ed8 --- /dev/null +++ b/samples/preauth/src/main/webapp/secure/index.jsp @@ -0,0 +1,15 @@ + + +

Secure Page

+This is a protected page. You can get to me if you've been remembered, +or if you've authenticated this session.

+ +<%if (request.isUserInRole("ROLE_SUPERVISOR")) { %> + You are a supervisor! You can therefore see the extremely secure page.

+<% } %> + + +

Home +

Logout + + \ No newline at end of file