浏览代码

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 年之前
父节点
当前提交
281d77271e
共有 25 个文件被更改,包括 192 次插入228 次删除
  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));