Browse Source

SEC-319: Reverted to 1.0.1 version to delay these changes to 1.1.0, based on small breakage of backward compatability.

Scott McCrory 19 năm trước cách đây
mục cha
commit
db96650d99

+ 88 - 34
core/src/main/java/org/acegisecurity/ui/webapp/SiteminderAuthenticationProcessingFilter.java

@@ -15,40 +15,36 @@
 
 package org.acegisecurity.ui.webapp;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
 import org.acegisecurity.Authentication;
 import org.acegisecurity.AuthenticationException;
+
 import org.acegisecurity.context.HttpSessionContextIntegrationFilter;
 import org.acegisecurity.context.SecurityContext;
+
 import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+
 /**
- * Extends Acegi's AuthenticationProcessingFilter to pick up CA/Netegrity Siteminder headers.
- * 
- * <P>Also provides a backup form-based authentication and the ability set source key names.</p>
- * 
- * <P><B>Siteminder</B> must present two <B>headers</B> to this filter, a username and password. You must set the
+ * Extends Acegi's AuthenticationProcessingFilter to pick up CA/Netegrity Siteminder headers.<P>Also provides a
+ * backup form-based authentication and the ability set source key names.</p>
+ *  <P><B>Siteminder</B> must present two <B>headers</B> to this filter, a username and password. You must set the
  * header keys before this filter is used for authentication, otherwise Siteminder checks will be skipped. If the
  * Siteminder check is unsuccessful (i.e. if the headers are not found), then the form parameters will be checked (see
  * next paragraph). This allows applications to optionally function even when their Siteminder infrastructure is
  * unavailable, as is often the case during development.</p>
- * 
- * <P><B>Login forms</B> must present two <B>parameters</B> to this filter: a username and password. If not
+ *  <P><B>Login forms</B> must present two <B>parameters</B> to this filter: a username and password. If not
  * specified, the parameter names to use are contained in the static fields {@link #ACEGI_SECURITY_FORM_USERNAME_KEY}
  * and {@link #ACEGI_SECURITY_FORM_PASSWORD_KEY}.</p>
- * 
- * <P><B>Do not use this class directly.</B> Instead, configure <code>web.xml</code> to use the {@link
+ *  <P><B>Do not use this class directly.</B> Instead, configure <code>web.xml</code> to use the {@link
  * org.acegisecurity.util.FilterToBeanProxy}.</p>
- * 
- * @author Scott McCrory
- * @version $Id$
  */
 public class SiteminderAuthenticationProcessingFilter extends AuthenticationProcessingFilter {
-
     //~ Static fields/initializers =====================================================================================
 
     /** Log instance for debugging */
@@ -56,15 +52,21 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
 
     //~ Instance fields ================================================================================================
 
+    /** Form password request key. */
+    private String formPasswordParameterKey = null;
+
     /** Form username request key. */
     private String formUsernameParameterKey = null;
 
+    /** Siteminder password header key. */
+    private String siteminderPasswordHeaderKey = null;
+
     /** Siteminder username header key. */
     private String siteminderUsernameHeaderKey = null;
 
     //~ Constructors ===================================================================================================
 
-    /**
+/**
      * Basic constructor.
      */
     public SiteminderAuthenticationProcessingFilter() {
@@ -74,19 +76,24 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
     //~ Methods ========================================================================================================
 
     /**
+     * 
      * @see org.acegisecurity.ui.AbstractProcessingFilter#attemptAuthentication(javax.servlet.http.HttpServletRequest)
      */
-    public Authentication attemptAuthentication(final HttpServletRequest request) throws AuthenticationException {
-
+    public Authentication attemptAuthentication(HttpServletRequest request)
+        throws AuthenticationException {
         String username = null;
+        String password = null;
 
-        // Check the Siteminder header for identification info
-        if ((siteminderUsernameHeaderKey != null) && (siteminderUsernameHeaderKey.length() > 0)) {
+        // Check the Siteminder headers for authentication info
+        if ((siteminderUsernameHeaderKey != null) && (siteminderUsernameHeaderKey.length() > 0)
+            && (siteminderPasswordHeaderKey != null) && (siteminderPasswordHeaderKey.length() > 0)) {
             username = request.getHeader(siteminderUsernameHeaderKey);
+            password = request.getHeader(siteminderPasswordHeaderKey);
         }
 
-        // If the Siteminder identification info wasn't available, then try to get it from the form
-        if ((username == null) || (username.length() == 0)) {
+        // If the Siteminder authentication info wasn't available, then get it
+        // from the form parameters
+        if ((username == null) || (username.length() == 0) || (password == null) || (password.length() == 0)) {
             if (logger.isDebugEnabled()) {
                 logger.debug("Siteminder headers not found for authentication, so trying to use form values");
             }
@@ -97,6 +104,7 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
                 username = request.getParameter(ACEGI_SECURITY_FORM_USERNAME_KEY);
             }
 
+            password = obtainPassword(request);
         }
 
         // Convert username and password to upper case. This is normally not a
@@ -109,9 +117,14 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
             username = "";
         }
 
-        // Pass in a null password value because it isn't relevant for Siteminder.
-        // Of course the AuthenticationManager needs to not care!
-        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, null);
+        if (password != null) {
+            password = password.toUpperCase();
+        } else {
+            // If password is null, set to blank to avoid a NPE.
+            password = "";
+        }
+
+        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
 
         // Allow subclasses to set the "details" property
         setDetails(request, authRequest);
@@ -122,6 +135,15 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
         return this.getAuthenticationManager().authenticate(authRequest);
     }
 
+    /**
+     * Returns the form password parameter key.
+     *
+     * @return The form password parameter key.
+     */
+    public String getFormPasswordParameterKey() {
+        return formPasswordParameterKey;
+    }
+
     /**
      * Returns the form username parameter key.
      *
@@ -131,6 +153,15 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
         return formUsernameParameterKey;
     }
 
+    /**
+     * Returns the Siteminder password header key.
+     *
+     * @return The Siteminder password header key.
+     */
+    public String getSiteminderPasswordHeaderKey() {
+        return siteminderPasswordHeaderKey;
+    }
+
     /**
      * Returns the Siteminder username header key.
      *
@@ -141,14 +172,20 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
     }
 
     /**
-     * Overridden method to always return a null (Siteminder doesn't pass on the password).
+     * Overridden method to obtain different value depending on whether Siteminder or form validation is being
+     * performed.
      *
      * @param request so that request attributes can be retrieved
+     *
      * @return the password that will be presented in the <code>Authentication</code> request token to the
-     *         <code>AuthenticationManager</code> (null).
+     *         <code>AuthenticationManager</code>
      */
-    protected String obtainPassword(final HttpServletRequest request) {
-        return null;
+    protected String obtainPassword(HttpServletRequest request) {
+        if ((formPasswordParameterKey != null) && (formPasswordParameterKey.length() > 0)) {
+            return request.getParameter(formPasswordParameterKey);
+        } else {
+            return request.getParameter(ACEGI_SECURITY_FORM_PASSWORD_KEY);
+        }
     }
 
     /**
@@ -160,7 +197,6 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
      *      javax.servlet.http.HttpServletResponse)
      */
     protected boolean requiresAuthentication(final HttpServletRequest request, final HttpServletResponse response) {
-
         String uri = request.getRequestURI();
         int pathParamIndex = uri.indexOf(';');
 
@@ -172,8 +208,8 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
         //attempt authentication if j_secuity_check is present or if the getDefaultTargetUrl() 
         //is present and user is not already authenticated. 
         boolean bAuthenticated = false;
-        SecurityContext context = (SecurityContext) request.getSession().getAttribute(
-                HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY);
+        SecurityContext context = (SecurityContext) request.getSession()
+                                                           .getAttribute(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY);
 
         if (context != null) {
             Authentication auth = context.getAuthentication();
@@ -186,7 +222,7 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
 
         // if true is returned then authentication will be attempted.
         boolean bAttemptAuthentication = (uri.endsWith(request.getContextPath() + getFilterProcessesUrl()))
-                || ((getDefaultTargetUrl() != null) && uri.endsWith(getDefaultTargetUrl()) && !bAuthenticated);
+            || ((getDefaultTargetUrl() != null) && uri.endsWith(getDefaultTargetUrl()) && !bAuthenticated);
 
         if (logger.isDebugEnabled()) {
             logger.debug("Authentication attempted for the following URI ==> " + uri + " is " + bAttemptAuthentication);
@@ -195,6 +231,15 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
         return bAttemptAuthentication;
     }
 
+    /**
+     * Sets the form password parameter key.
+     *
+     * @param key The form password parameter key.
+     */
+    public void setFormPasswordParameterKey(final String key) {
+        this.formPasswordParameterKey = key;
+    }
+
     /**
      * Sets the form username parameter key.
      *
@@ -204,6 +249,15 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
         this.formUsernameParameterKey = key;
     }
 
+    /**
+     * Sets the Siteminder password header key.
+     *
+     * @param key The Siteminder password header key.
+     */
+    public void setSiteminderPasswordHeaderKey(final String key) {
+        this.siteminderPasswordHeaderKey = key;
+    }
+
     /**
      * Sets the Siteminder username header key.
      *