Browse Source

SEC-1486, SEC-1538, SEC-1537: Generification of AuthenticationDetailsSource. Deprecation of non-web pre-authentication classes and other unnecessary classes. Removal of reflection in WebAuthenticationDetailsSource.

Luke Taylor 15 năm trước cách đây
mục cha
commit
281d77271e
25 tập tin đã thay đổi với 192 bổ sung228 xóa
  1. 1 0
      core/src/main/java/org/springframework/security/authentication/AuthenticationDetails.java
  2. 2 2
      core/src/main/java/org/springframework/security/authentication/AuthenticationDetailsSource.java
  3. 4 3
      core/src/main/java/org/springframework/security/authentication/AuthenticationDetailsSourceImpl.java
  4. 1 0
      core/src/main/java/org/springframework/security/core/authority/GrantedAuthoritiesContainerImpl.java
  5. 1 0
      core/src/main/java/org/springframework/security/core/authority/MutableGrantedAuthoritiesContainer.java
  6. 2 0
      core/src/main/java/org/springframework/security/core/session/SessionIdentifierAware.java
  7. 3 2
      samples/gae/src/main/java/samples/gae/security/GaeAuthenticationFilter.java
  8. 2 7
      web/src/main/java/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.java
  9. 3 2
      web/src/main/java/org/springframework/security/web/authentication/AnonymousAuthenticationFilter.java
  10. 4 8
      web/src/main/java/org/springframework/security/web/authentication/WebAuthenticationDetails.java
  11. 6 31
      web/src/main/java/org/springframework/security/web/authentication/WebAuthenticationDetailsSource.java
  12. 3 2
      web/src/main/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java
  13. 17 17
      web/src/main/java/org/springframework/security/web/authentication/preauth/PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.java
  14. 0 92
      web/src/main/java/org/springframework/security/web/authentication/preauth/j2ee/AbstractPreAuthenticatedAuthenticationDetailsSource.java
  15. 69 16
      web/src/main/java/org/springframework/security/web/authentication/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.java
  16. 4 4
      web/src/main/java/org/springframework/security/web/authentication/preauth/websphere/WebSphere2SpringSecurityPropagationInterceptor.java
  17. 1 0
      web/src/main/java/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedAuthenticationDetailsSource.java
  18. 1 0
      web/src/main/java/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedProcessingFilter.java
  19. 50 12
      web/src/main/java/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedWebAuthenticationDetailsSource.java
  20. 3 3
      web/src/main/java/org/springframework/security/web/authentication/rememberme/AbstractRememberMeServices.java
  21. 1 1
      web/src/main/java/org/springframework/security/web/authentication/switchuser/SwitchUserFilter.java
  22. 2 2
      web/src/main/java/org/springframework/security/web/authentication/www/BasicAuthenticationFilter.java
  23. 2 2
      web/src/main/java/org/springframework/security/web/authentication/www/DigestAuthenticationFilter.java
  24. 8 19
      web/src/test/java/org/springframework/security/web/authentication/preauth/PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetailsTests.java
  25. 2 3
      web/src/test/java/org/springframework/security/web/authentication/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSourceTests.java

+ 1 - 0
core/src/main/java/org/springframework/security/authentication/AuthenticationDetails.java

@@ -8,6 +8,7 @@ import java.io.Serializable;
 * @author Ruud Senden
 * @since 2.0
 */
+@Deprecated
 public class AuthenticationDetails implements Serializable {
    //~ Instance fields ================================================================================================
 

+ 2 - 2
core/src/main/java/org/springframework/security/authentication/AuthenticationDetailsSource.java

@@ -21,7 +21,7 @@ package org.springframework.security.authentication;
  *
  * @author Ben Alex
  */
-public interface AuthenticationDetailsSource {
+public interface AuthenticationDetailsSource<C, T> {
     //~ Methods ========================================================================================================
 
     /**
@@ -31,5 +31,5 @@ public interface AuthenticationDetailsSource {
      *
      * @return a fully-configured authentication details instance
      */
-    Object buildDetails(Object context);
+    T buildDetails(C context);
 }

+ 4 - 3
core/src/main/java/org/springframework/security/authentication/AuthenticationDetailsSourceImpl.java

@@ -1,11 +1,10 @@
 package org.springframework.security.authentication;
 
-import java.lang.reflect.Constructor;
-
-import org.springframework.security.authentication.AuthenticationDetailsSource;
 import org.springframework.util.Assert;
 import org.springframework.util.ReflectionUtils;
 
+import java.lang.reflect.Constructor;
+
 /**
  * Base implementation of {@link AuthenticationDetailsSource}.
  * <p>
@@ -16,7 +15,9 @@ import org.springframework.util.ReflectionUtils;
  *
  * @author Ruud Senden
  * @since 2.0
+ * @deprecated Write an implementation of AuthenticationDetailsSource which returns the desired type directly.
  */
+@Deprecated
 public class AuthenticationDetailsSourceImpl implements AuthenticationDetailsSource {
     //~ Instance fields ================================================================================================
 

+ 1 - 0
core/src/main/java/org/springframework/security/core/authority/GrantedAuthoritiesContainerImpl.java

@@ -6,6 +6,7 @@ import java.util.List;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.util.Assert;
 
+@Deprecated
 public class GrantedAuthoritiesContainerImpl implements MutableGrantedAuthoritiesContainer {
     private List<GrantedAuthority> authorities;
 

+ 1 - 0
core/src/main/java/org/springframework/security/core/authority/MutableGrantedAuthoritiesContainer.java

@@ -14,6 +14,7 @@ import org.springframework.security.core.GrantedAuthority;
  * @author Luke Taylor
  * @since 2.0
  */
+@Deprecated
 public interface MutableGrantedAuthoritiesContainer extends GrantedAuthoritiesContainer {
     /**
      * Used to store authorities in the containing object.

+ 2 - 0
core/src/main/java/org/springframework/security/core/session/SessionIdentifierAware.java

@@ -22,7 +22,9 @@ package org.springframework.security.core.session;
  * Used to extract the session ID from an <code>Authentication</code> object.
  *
  * @author Ben Alex
+ * @deprecated Legacy of former concurrency control implementation. Will be removed in a future version.
  */
+@Deprecated
 public interface SessionIdentifierAware {
     //~ Methods ========================================================================================================
 

+ 3 - 2
samples/gae/src/main/java/samples/gae/security/GaeAuthenticationFilter.java

@@ -19,6 +19,7 @@ import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.web.authentication.AuthenticationFailureHandler;
 import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
+import org.springframework.security.web.authentication.WebAuthenticationDetails;
 import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
 import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
 import org.springframework.util.Assert;
@@ -32,7 +33,7 @@ public class GaeAuthenticationFilter extends GenericFilterBean {
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
-    private final AuthenticationDetailsSource ads = new WebAuthenticationDetailsSource();
+    private final AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> ads = new WebAuthenticationDetailsSource();
     private AuthenticationManager authenticationManager;
     private AuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();
 
@@ -47,7 +48,7 @@ public class GaeAuthenticationFilter extends GenericFilterBean {
                 logger.debug("Authenticating to Spring Security");
                 // User has returned after authenticating via GAE. Need to authenticate through Spring Security.
                 PreAuthenticatedAuthenticationToken token = new PreAuthenticatedAuthenticationToken(googleUser, null);
-                token.setDetails(ads.buildDetails(request));
+                token.setDetails(ads.buildDetails((HttpServletRequest) request));
 
                 try {
                     authentication = authenticationManager.authenticate(token);

+ 2 - 7
web/src/main/java/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.java

@@ -110,7 +110,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
     //~ Instance fields ================================================================================================
 
     protected ApplicationEventPublisher eventPublisher;
-    protected AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
+    protected AuthenticationDetailsSource<HttpServletRequest,?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
     private AuthenticationManager authenticationManager;
     protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
 
@@ -363,7 +363,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
         this.eventPublisher = eventPublisher;
     }
 
-    public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
+    public void setAuthenticationDetailsSource(AuthenticationDetailsSource<HttpServletRequest,?> authenticationDetailsSource) {
         Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
         this.authenticationDetailsSource = authenticationDetailsSource;
     }
@@ -372,11 +372,6 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
         this.messages = new MessageSourceAccessor(messageSource);
     }
 
-    public AuthenticationDetailsSource getAuthenticationDetailsSource() {
-        // Required due to SEC-310
-        return authenticationDetailsSource;
-    }
-
     protected boolean getAllowSessionCreation() {
         return allowSessionCreation;
     }

+ 3 - 2
web/src/main/java/org/springframework/security/web/authentication/AnonymousAuthenticationFilter.java

@@ -44,7 +44,8 @@ public class AnonymousAuthenticationFilter extends GenericFilterBean  implements
 
     //~ Instance fields ================================================================================================
 
-    private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
+    private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource
+            = new WebAuthenticationDetailsSource();
     private String key;
     private UserAttribute userAttribute;
 
@@ -109,7 +110,7 @@ public class AnonymousAuthenticationFilter extends GenericFilterBean  implements
         return userAttribute;
     }
 
-    public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
+    public void setAuthenticationDetailsSource(AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource) {
         Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
         this.authenticationDetailsSource = authenticationDetailsSource;
     }

+ 4 - 8
web/src/main/java/org/springframework/security/web/authentication/WebAuthenticationDetails.java

@@ -15,10 +15,6 @@
 
 package org.springframework.security.web.authentication;
 
-import org.springframework.security.core.session.SessionIdentifierAware;
-
-import java.io.Serializable;
-
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
 
@@ -28,7 +24,7 @@ import javax.servlet.http.HttpSession;
  *
  * @author Ben Alex
  */
-public class WebAuthenticationDetails implements SessionIdentifierAware, Serializable {
+public class WebAuthenticationDetails {
     //~ Instance fields ================================================================================================
 
     private final String remoteAddress;
@@ -132,9 +128,9 @@ public class WebAuthenticationDetails implements SessionIdentifierAware, Seriali
 
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        sb.append(super.toString() + ": ");
-        sb.append("RemoteIpAddress: " + this.getRemoteAddress() + "; ");
-        sb.append("SessionId: " + this.getSessionId());
+        sb.append(super.toString()).append(": ");
+        sb.append("RemoteIpAddress: ").append(this.getRemoteAddress()).append("; ");
+        sb.append("SessionId: ").append(this.getSessionId());
 
         return sb.toString();
     }

+ 6 - 31
web/src/main/java/org/springframework/security/web/authentication/WebAuthenticationDetailsSource.java

@@ -27,44 +27,19 @@ import javax.servlet.http.HttpServletRequest;
 
 /**
  * Implementation of {@link AuthenticationDetailsSource} which builds the details object from
- * an <tt>HttpServletRequest</tt> object.
- * <p>
- * By default will create an instance of <code>WebAuthenticationDetails</code>. Any object that accepts a
- * <code>HttpServletRequest</code> as its sole constructor can be used instead of this default.
+ * an <tt>HttpServletRequest</tt> object, creating a {@code WebAuthenticationDetails}.
  *
  * @author Ben Alex
  */
-public class WebAuthenticationDetailsSource implements AuthenticationDetailsSource {
-    //~ Instance fields ================================================================================================
-
-    private Class<?> clazz = WebAuthenticationDetails.class;
+public class WebAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> {
 
     //~ Methods ========================================================================================================
 
     /**
-     * @param context the <tt>HttpServletRequest</tt> object.
+     * @param context the {@code HttpServletRequest} object.
+     * @return the {@code WebAuthenticationDetails} containing information about the current request
      */
-    public Object buildDetails(Object context) {
-        Assert.isInstanceOf(HttpServletRequest.class, context);
-        try {
-            Constructor<?> constructor = clazz.getConstructor(HttpServletRequest.class);
-
-            return constructor.newInstance(context);
-        } catch (NoSuchMethodException ex) {
-            ReflectionUtils.handleReflectionException(ex);
-        } catch (InvocationTargetException ex) {
-            ReflectionUtils.handleReflectionException(ex);
-        } catch (InstantiationException ex) {
-            ReflectionUtils.handleReflectionException(ex);
-        } catch (IllegalAccessException ex) {
-            ReflectionUtils.handleReflectionException(ex);
-        }
-
-        return null;
-    }
-
-    public void setClazz(Class<?> clazz) {
-        Assert.notNull(clazz, "Class required");
-        this.clazz = clazz;
+    public WebAuthenticationDetails buildDetails(HttpServletRequest context) {
+        return new WebAuthenticationDetails(context);
     }
 }

+ 3 - 2
web/src/main/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java

@@ -56,7 +56,8 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
         ApplicationEventPublisherAware {
 
     private ApplicationEventPublisher eventPublisher = null;
-    private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
+    private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource
+            = new WebAuthenticationDetailsSource();
     private AuthenticationManager authenticationManager = null;
     private boolean continueFilterChainOnUnsuccessfulAuthentication = true;
     private boolean checkForPrincipalChanges;
@@ -190,7 +191,7 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
      * @param authenticationDetailsSource
      *            The AuthenticationDetailsSource to use
      */
-    public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
+    public void setAuthenticationDetailsSource(AuthenticationDetailsSource<HttpServletRequest,?> authenticationDetailsSource) {
         Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
         this.authenticationDetailsSource = authenticationDetailsSource;
     }

+ 17 - 17
web/src/main/java/org/springframework/security/web/authentication/preauth/PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.java

@@ -1,14 +1,14 @@
 package org.springframework.security.web.authentication.preauth;
 
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-
 import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.GrantedAuthoritiesContainerImpl;
-import org.springframework.security.core.authority.MutableGrantedAuthoritiesContainer;
+import org.springframework.security.core.authority.GrantedAuthoritiesContainer;
 import org.springframework.security.web.authentication.WebAuthenticationDetails;
 
+import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 /**
  * This WebAuthenticationDetails implementation allows for storing a list of
  * pre-authenticated Granted Authorities.
@@ -18,27 +18,27 @@ import org.springframework.security.web.authentication.WebAuthenticationDetails;
  * @since 2.0
  */
 public class PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails extends WebAuthenticationDetails implements
-        MutableGrantedAuthoritiesContainer {
-    public static final long serialVersionUID = 1L;
+        GrantedAuthoritiesContainer {
 
-    private final MutableGrantedAuthoritiesContainer authoritiesContainer = new GrantedAuthoritiesContainerImpl();
+    private final List<GrantedAuthority> authorities;
 
-    public PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(HttpServletRequest request) {
+    public PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(HttpServletRequest request,
+            List<GrantedAuthority> authorities) {
         super(request);
-    }
 
-    public List<GrantedAuthority> getGrantedAuthorities() {
-        return authoritiesContainer.getGrantedAuthorities();
+        List<GrantedAuthority> temp = new ArrayList<GrantedAuthority>(authorities.size());
+        temp.addAll(authorities);
+        this.authorities = Collections.unmodifiableList(temp);
     }
 
-    public void setGrantedAuthorities(List<GrantedAuthority> authorities) {
-        this.authoritiesContainer.setGrantedAuthorities(authorities);
+    public List<GrantedAuthority> getGrantedAuthorities() {
+        return authorities;
     }
 
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        sb.append(super.toString() + "; ");
-        sb.append(authoritiesContainer);
+        sb.append(super.toString()).append("; ");
+        sb.append(authorities);
         return sb.toString();
     }
 }

+ 0 - 92
web/src/main/java/org/springframework/security/web/authentication/preauth/j2ee/AbstractPreAuthenticatedAuthenticationDetailsSource.java

@@ -1,92 +0,0 @@
-package org.springframework.security.web.authentication.preauth.j2ee;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.security.authentication.AuthenticationDetailsSourceImpl;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.MutableGrantedAuthoritiesContainer;
-import org.springframework.security.core.authority.mapping.Attributes2GrantedAuthoritiesMapper;
-import org.springframework.security.core.authority.mapping.MappableAttributesRetriever;
-import org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper;
-import org.springframework.util.Assert;
-
-/**
- * Base implementation for classes scenarios where the authentication details object is used
- * to store a list of authorities obtained from the context object (such as an HttpServletRequest)
- * passed to {@link #buildDetails(Object)}.
- * <p>
- *
- *
- * @author Luke Taylor
- * @since 2.0
- */
-public abstract class AbstractPreAuthenticatedAuthenticationDetailsSource extends AuthenticationDetailsSourceImpl {
-    protected final Log logger = LogFactory.getLog(getClass());
-    protected Set<String> j2eeMappableRoles;
-    protected Attributes2GrantedAuthoritiesMapper j2eeUserRoles2GrantedAuthoritiesMapper =
-        new SimpleAttributes2GrantedAuthoritiesMapper();
-
-    public AbstractPreAuthenticatedAuthenticationDetailsSource() {
-    }
-
-    /**
-     * Check that all required properties have been set.
-     */
-    public void afterPropertiesSet() throws Exception {
-        Assert.notNull(j2eeMappableRoles, "No mappable roles available");
-        Assert.notNull(j2eeUserRoles2GrantedAuthoritiesMapper, "Roles to granted authorities mapper not set");
-    }
-
-    /**
-     * Build the authentication details object. If the specified authentication
-     * details class implements {@link MutableGrantedAuthoritiesContainer}, a
-     * list of pre-authenticated Granted Authorities will be set based on the
-     * roles for the current user.
-     *
-     * @see org.springframework.security.authentication.AuthenticationDetailsSource#buildDetails(Object)
-     */
-    public Object buildDetails(Object context) {
-        Object result = super.buildDetails(context);
-
-        if (result instanceof MutableGrantedAuthoritiesContainer) {
-            Collection<String> j2eeUserRoles = getUserRoles(context, j2eeMappableRoles);
-            List<GrantedAuthority> userGas = j2eeUserRoles2GrantedAuthoritiesMapper.getGrantedAuthorities(j2eeUserRoles);
-
-            if (logger.isDebugEnabled()) {
-                logger.debug("J2EE roles [" + j2eeUserRoles + "] mapped to Granted Authorities: [" + userGas + "]");
-            }
-
-            ((MutableGrantedAuthoritiesContainer) result).setGrantedAuthorities(userGas);
-        }
-        return result;
-    }
-
-    /**
-     * Allows the roles of the current user to be determined from the context object
-     *
-     * @param context the context object (an HttpRequest, PortletRequest etc)
-     * @param mappableRoles the possible roles as determined by the MappableAttributesRetriever
-     * @return the subset of mappable roles which the current user has.
-     */
-    protected abstract Collection<String> getUserRoles(Object context, Set<String> mappableRoles);
-
-    /**
-     * @param aJ2eeMappableRolesRetriever
-     *            The MappableAttributesRetriever to use
-     */
-    public void setMappableRolesRetriever(MappableAttributesRetriever aJ2eeMappableRolesRetriever) {
-        this.j2eeMappableRoles = aJ2eeMappableRolesRetriever.getMappableAttributes();
-    }
-
-    /**
-     * @param mapper
-     *            The Attributes2GrantedAuthoritiesMapper to use
-     */
-    public void setUserRoles2GrantedAuthoritiesMapper(Attributes2GrantedAuthoritiesMapper mapper) {
-        j2eeUserRoles2GrantedAuthoritiesMapper = mapper;
-    }
-}

+ 69 - 16
web/src/main/java/org/springframework/security/web/authentication/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.java

@@ -1,13 +1,18 @@
 package org.springframework.security.web.authentication.preauth.j2ee;
 
-import org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.security.authentication.AuthenticationDetailsSource;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.mapping.Attributes2GrantedAuthoritiesMapper;
+import org.springframework.security.core.authority.mapping.MappableAttributesRetriever;
 import org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Set;
+import org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails;
+import org.springframework.util.Assert;
 
 import javax.servlet.http.HttpServletRequest;
+import java.util.*;
 
 /**
  * Implementation of AuthenticationDetailsSource which converts the user's J2EE roles (as obtained by calling
@@ -17,29 +22,77 @@ import javax.servlet.http.HttpServletRequest;
  * @author Ruud Senden
  * @since 2.0
  */
-public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource extends AbstractPreAuthenticatedAuthenticationDetailsSource {
+public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
+        implements AuthenticationDetailsSource<HttpServletRequest, PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails>,
+        InitializingBean {
+
+    protected final Log logger = LogFactory.getLog(getClass());
+    /** The role attributes returned by the configured {@code MappableAttributesRetriever} */
+    protected Set<String> j2eeMappableRoles;
+    protected Attributes2GrantedAuthoritiesMapper j2eeUserRoles2GrantedAuthoritiesMapper =
+        new SimpleAttributes2GrantedAuthoritiesMapper();
+
     /**
-     * Public constructor which overrides the default {@code WebAuthenticationDetails}
-     * class to be used.
+     * Check that all required properties have been set.
      */
-    public J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource() {
-        super.setClazz(PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.class);
-
-        j2eeUserRoles2GrantedAuthoritiesMapper = new SimpleAttributes2GrantedAuthoritiesMapper();
+    public void afterPropertiesSet() throws Exception {
+        Assert.notNull(j2eeMappableRoles, "No mappable roles available");
+        Assert.notNull(j2eeUserRoles2GrantedAuthoritiesMapper, "Roles to granted authorities mapper not set");
     }
 
     /**
-     * Obtains the list of user roles based on the current user's J2EE roles.
+     * Obtains the list of user roles based on the current user's JEE roles. The
+     * {@link javax.servlet.http.HttpServletRequest#isUserInRole(String)} method is called for each of the values
+     * in the {@code j2eeMappableRoles} set to determine if that role should be assigned to the user.
+     *
+     * @param request the request which should be used to extract the user's roles.
+     * @return The subset of {@code j2eeMappableRoles} which applies to the current user making the request.
      */
-    protected Collection<String> getUserRoles(Object context, Set<String> mappableRoles) {
+    protected Collection<String> getUserRoles(HttpServletRequest request) {
         ArrayList<String> j2eeUserRolesList = new ArrayList<String>();
 
-        for (String role : mappableRoles) {
-            if (((HttpServletRequest)context).isUserInRole(role)) {
+        for (String role : j2eeMappableRoles) {
+            if (request.isUserInRole(role)) {
                 j2eeUserRolesList.add(role);
             }
         }
 
         return j2eeUserRolesList;
     }
+
+    /**
+     * Builds the authentication details object.
+     *
+     * @see org.springframework.security.authentication.AuthenticationDetailsSource#buildDetails(Object)
+     */
+    public PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails buildDetails(HttpServletRequest context) {
+
+        Collection<String> j2eeUserRoles = getUserRoles(context);
+        List<GrantedAuthority> userGas = j2eeUserRoles2GrantedAuthoritiesMapper.getGrantedAuthorities(j2eeUserRoles);
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("J2EE roles [" + j2eeUserRoles + "] mapped to Granted Authorities: [" + userGas + "]");
+        }
+
+        PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails result =
+                new PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(context, userGas);
+
+        return result;
+    }
+
+    /**
+     * @param aJ2eeMappableRolesRetriever
+     *            The MappableAttributesRetriever to use
+     */
+    public void setMappableRolesRetriever(MappableAttributesRetriever aJ2eeMappableRolesRetriever) {
+        this.j2eeMappableRoles = Collections.unmodifiableSet(aJ2eeMappableRolesRetriever.getMappableAttributes());
+    }
+
+    /**
+     * @param mapper
+     *            The Attributes2GrantedAuthoritiesMapper to use
+     */
+    public void setUserRoles2GrantedAuthoritiesMapper(Attributes2GrantedAuthoritiesMapper mapper) {
+        j2eeUserRoles2GrantedAuthoritiesMapper = mapper;
+    }
 }

+ 4 - 4
web/src/main/java/org/springframework/security/web/authentication/preauth/websphere/WebSphere2SpringSecurityPropagationInterceptor.java

@@ -18,10 +18,11 @@ import org.springframework.util.Assert;
  * @author Ruud Senden
  * @since 1.0
  */
+@Deprecated
 public class WebSphere2SpringSecurityPropagationInterceptor implements MethodInterceptor {
     private static final Log logger = LogFactory.getLog(WebSphere2SpringSecurityPropagationInterceptor.class);
     private AuthenticationManager authenticationManager = null;
-    private AuthenticationDetailsSource authenticationDetailsSource = new WebSpherePreAuthenticatedAuthenticationDetailsSource();
+    private AuthenticationDetailsSource<?,?> authenticationDetailsSource = new WebSpherePreAuthenticatedAuthenticationDetailsSource();
     private final WASUsernameAndGroupsExtractor wasHelper;
 
     public WebSphere2SpringSecurityPropagationInterceptor() {
@@ -40,7 +41,7 @@ public class WebSphere2SpringSecurityPropagationInterceptor implements MethodInt
     public Object invoke(MethodInvocation methodInvocation) throws Throwable {
         try {
             logger.debug("Performing Spring Security authentication with WebSphere credentials");
-            authenticateSpringSecurityWithWASCredentials(this);
+            authenticateSpringSecurityWithWASCredentials();
             logger.debug("Proceeding with method invocation");
             return methodInvocation.proceed();
         } finally {
@@ -52,9 +53,8 @@ public class WebSphere2SpringSecurityPropagationInterceptor implements MethodInt
     /**
      * Retrieve the current WebSphere credentials and authenticate them with Spring Security
      * using the pre-authenticated authentication provider.
-     * @param aContext The context to use for building the authentication details.
      */
-    private void authenticateSpringSecurityWithWASCredentials(Object aContext) {
+    private void authenticateSpringSecurityWithWASCredentials() {
         Assert.notNull(authenticationManager);
         Assert.notNull(authenticationDetailsSource);
 

+ 1 - 0
web/src/main/java/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedAuthenticationDetailsSource.java

@@ -23,6 +23,7 @@ import org.springframework.util.Assert;
  *
  * @author Ruud Senden
  */
+@Deprecated
 public class WebSpherePreAuthenticatedAuthenticationDetailsSource extends AuthenticationDetailsSourceImpl implements InitializingBean {
     private final Log logger = LogFactory.getLog(getClass());
 

+ 1 - 0
web/src/main/java/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedProcessingFilter.java

@@ -25,6 +25,7 @@ public class WebSpherePreAuthenticatedProcessingFilter extends AbstractPreAuthen
 
     WebSpherePreAuthenticatedProcessingFilter(WASUsernameAndGroupsExtractor wasHelper) {
         this.wasHelper = wasHelper;
+        setAuthenticationDetailsSource(new WebSpherePreAuthenticatedWebAuthenticationDetailsSource());
     }
 
 

+ 50 - 12
web/src/main/java/org/springframework/security/web/authentication/preauth/websphere/WebSpherePreAuthenticatedWebAuthenticationDetailsSource.java

@@ -1,24 +1,62 @@
 package org.springframework.security.web.authentication.preauth.websphere;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.security.authentication.AuthenticationDetailsSource;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.mapping.Attributes2GrantedAuthoritiesMapper;
+import org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper;
 import org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails;
 
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
 /**
- * This AuthenticationDetailsSource implementation, when configured with a MutableGrantedAuthoritiesContainer,
- * will set the pre-authenticated granted authorities based on the WebSphere groups for the current WebSphere
- * user, mapped using the configured Attributes2GrantedAuthoritiesMapper.
- *
- * By default, this class is configured to build instances of the
- * PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails class.
+ * This AuthenticationDetailsSource implementation will set the pre-authenticated granted
+ * authorities based on the WebSphere groups for the current WebSphere user, mapped using the
+ * configured Attributes2GrantedAuthoritiesMapper.
  *
  * @author Ruud Senden
  */
-public class WebSpherePreAuthenticatedWebAuthenticationDetailsSource extends WebSpherePreAuthenticatedAuthenticationDetailsSource {
+public class WebSpherePreAuthenticatedWebAuthenticationDetailsSource implements
+        AuthenticationDetailsSource<HttpServletRequest, PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails> {
+    private final Log logger = LogFactory.getLog(getClass());
+
+    private Attributes2GrantedAuthoritiesMapper webSphereGroups2GrantedAuthoritiesMapper = new SimpleAttributes2GrantedAuthoritiesMapper();
+
+    private final WASUsernameAndGroupsExtractor wasHelper;
+
+    public WebSpherePreAuthenticatedWebAuthenticationDetailsSource() {
+        this(new DefaultWASUsernameAndGroupsExtractor());
+    }
+
+    public WebSpherePreAuthenticatedWebAuthenticationDetailsSource(WASUsernameAndGroupsExtractor wasHelper) {
+        this.wasHelper = wasHelper;
+    }
+
+    public PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails buildDetails(HttpServletRequest context) {
+        return new PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(context, getWebSphereGroupsBasedGrantedAuthorities());
+    }
+
     /**
-     * Public constructor which overrides the default AuthenticationDetails
-     * class to be used.
+     * Get a list of Granted Authorities based on the current user's WebSphere groups.
+     *
+     * @return authorities mapped from the user's WebSphere groups.
      */
-    public WebSpherePreAuthenticatedWebAuthenticationDetailsSource() {
-        super();
-        super.setClazz(PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.class);
+    private List<GrantedAuthority> getWebSphereGroupsBasedGrantedAuthorities() {
+        List<String> webSphereGroups = wasHelper.getGroupsForCurrentUser();
+        List<GrantedAuthority> userGas = webSphereGroups2GrantedAuthoritiesMapper.getGrantedAuthorities(webSphereGroups);
+        if (logger.isDebugEnabled()) {
+            logger.debug("WebSphere groups: " + webSphereGroups + " mapped to Granted Authorities: " + userGas);
+        }
+        return userGas;
     }
+
+    /**
+     * @param mapper The Attributes2GrantedAuthoritiesMapper to use for converting the WAS groups to authorities
+     */
+    public void setWebSphereGroups2GrantedAuthoritiesMapper(Attributes2GrantedAuthoritiesMapper mapper) {
+        webSphereGroups2GrantedAuthoritiesMapper = mapper;
+    }
+
 }

+ 3 - 3
web/src/main/java/org/springframework/security/web/authentication/rememberme/AbstractRememberMeServices.java

@@ -47,7 +47,7 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
 
     private UserDetailsService userDetailsService;
     private final UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
-    private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
+    private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
 
     private String cookieName = SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY;
     private String parameter = DEFAULT_PARAMETER;
@@ -395,11 +395,11 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
         this.useSecureCookie = useSecureCookie;
     }
 
-    protected AuthenticationDetailsSource getAuthenticationDetailsSource() {
+    protected AuthenticationDetailsSource<HttpServletRequest,?> getAuthenticationDetailsSource() {
         return authenticationDetailsSource;
     }
 
-    public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
+    public void setAuthenticationDetailsSource(AuthenticationDetailsSource<HttpServletRequest,?> authenticationDetailsSource) {
         Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource cannot be null");
         this.authenticationDetailsSource = authenticationDetailsSource;
     }

+ 1 - 1
web/src/main/java/org/springframework/security/web/authentication/switchuser/SwitchUserFilter.java

@@ -109,7 +109,7 @@ public class SwitchUserFilter extends GenericFilterBean implements ApplicationEv
     //~ Instance fields ================================================================================================
 
     private ApplicationEventPublisher eventPublisher;
-    private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
+    private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
     protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
     private String exitUserUrl = "/j_spring_security_exit_user";
     private String switchUserUrl = "/j_spring_security_switch_user";

+ 2 - 2
web/src/main/java/org/springframework/security/web/authentication/www/BasicAuthenticationFilter.java

@@ -89,7 +89,7 @@ public class BasicAuthenticationFilter extends GenericFilterBean {
 
     //~ Instance fields ================================================================================================
 
-    private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
+    private AuthenticationDetailsSource<HttpServletRequest,?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
     private AuthenticationEntryPoint authenticationEntryPoint;
     private AuthenticationManager authenticationManager;
     private RememberMeServices rememberMeServices = new NullRememberMeServices();
@@ -257,7 +257,7 @@ public class BasicAuthenticationFilter extends GenericFilterBean {
         this.ignoreFailure = ignoreFailure;
     }
 
-    public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
+    public void setAuthenticationDetailsSource(AuthenticationDetailsSource<HttpServletRequest,?> authenticationDetailsSource) {
         Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
         this.authenticationDetailsSource = authenticationDetailsSource;
     }

+ 2 - 2
web/src/main/java/org/springframework/security/web/authentication/www/DigestAuthenticationFilter.java

@@ -88,7 +88,7 @@ public class DigestAuthenticationFilter extends GenericFilterBean implements Mes
 
     //~ Instance fields ================================================================================================
 
-    private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
+    private AuthenticationDetailsSource<HttpServletRequest,?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
     private DigestAuthenticationEntryPoint authenticationEntryPoint;
     protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
     private UserCache userCache = new NullUserCache();
@@ -246,7 +246,7 @@ public class DigestAuthenticationFilter extends GenericFilterBean implements Mes
         return userDetailsService;
     }
 
-    public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
+    public void setAuthenticationDetailsSource(AuthenticationDetailsSource<HttpServletRequest,?> authenticationDetailsSource) {
         Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
         this.authenticationDetailsSource = authenticationDetailsSource;
     }

+ 8 - 19
web/src/test/java/org/springframework/security/web/authentication/preauth/PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetailsTests.java

@@ -2,18 +2,16 @@ package org.springframework.security.web.authentication.preauth;
 
 import static org.junit.Assert.assertTrue;
 
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.servlet.http.HttpServletRequest;
-
 import org.junit.Test;
 import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.AuthorityUtils;
-import org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 
 /**
  * @author TSARDD
@@ -24,8 +22,7 @@ public class PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetailsTests {
     @Test
     public void testToString() {
         PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails details = new PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(
-                getRequest("testUser", new String[] {}));
-        details.setGrantedAuthorities(gas);
+                getRequest("testUser", new String[] {}), gas);
         String toString = details.toString();
         assertTrue("toString should contain Role1", toString.contains("Role1"));
         assertTrue("toString should contain Role2", toString.contains("Role2"));
@@ -34,20 +31,12 @@ public class PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetailsTests {
     @Test
     public void testGetSetPreAuthenticatedGrantedAuthorities() {
         PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails details = new PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(
-                getRequest("testUser", new String[] {}));
-        details.setGrantedAuthorities(gas);
+                getRequest("testUser", new String[] {}), gas);
         List<GrantedAuthority> returnedGas = details.getGrantedAuthorities();
         assertTrue("Collections do not contain same elements; expected: " + gas + ", returned: " + returnedGas,
                 gas.containsAll(returnedGas) && returnedGas.containsAll(gas));
     }
 
-    @Test(expected=IllegalArgumentException.class)
-    public void testGetWithoutSetPreAuthenticatedGrantedAuthorities() {
-        PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails details = new PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(
-                getRequest("testUser", new String[] {}));
-        details.getGrantedAuthorities();
-    }
-
     private HttpServletRequest getRequest(final String userName,final String[] aRoles) {
         MockHttpServletRequest req = new MockHttpServletRequest() {
             private Set<String> roles = new HashSet<String>(Arrays.asList(aRoles));

+ 2 - 3
web/src/test/java/org/springframework/security/web/authentication/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSourceTests.java

@@ -104,12 +104,11 @@ public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSourceTests extend
                 && gasRolesSet.containsAll(expectedRolesColl));
     }
 
-    private final J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource getJ2eeBasedPreAuthenticatedWebAuthenticationDetailsSource(
+    private J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource getJ2eeBasedPreAuthenticatedWebAuthenticationDetailsSource(
             String[] mappedRoles) {
         J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource result = new J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource();
         result.setMappableRolesRetriever(getMappableRolesRetriever(mappedRoles));
         result.setUserRoles2GrantedAuthoritiesMapper(getJ2eeUserRoles2GrantedAuthoritiesMapper());
-        result.setClazz(PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.class);
 
         try {
             result.afterPropertiesSet();
@@ -134,7 +133,7 @@ public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSourceTests extend
         return result;
     }
 
-    private final HttpServletRequest getRequest(final String userName,final String[] aRoles)
+    private HttpServletRequest getRequest(final String userName,final String[] aRoles)
     {
         MockHttpServletRequest req = new MockHttpServletRequest() {
             private Set<String> roles = new HashSet<String>(Arrays.asList(aRoles));