|
@@ -15,40 +15,36 @@
|
|
|
|
|
|
package org.acegisecurity.ui.webapp;
|
|
package org.acegisecurity.ui.webapp;
|
|
|
|
|
|
-import javax.servlet.http.HttpServletRequest;
|
|
|
|
-import javax.servlet.http.HttpServletResponse;
|
|
|
|
-
|
|
|
|
import org.acegisecurity.Authentication;
|
|
import org.acegisecurity.Authentication;
|
|
import org.acegisecurity.AuthenticationException;
|
|
import org.acegisecurity.AuthenticationException;
|
|
|
|
+
|
|
import org.acegisecurity.context.HttpSessionContextIntegrationFilter;
|
|
import org.acegisecurity.context.HttpSessionContextIntegrationFilter;
|
|
import org.acegisecurity.context.SecurityContext;
|
|
import org.acegisecurity.context.SecurityContext;
|
|
|
|
+
|
|
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
|
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
|
|
|
+
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
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
|
|
* 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
|
|
* 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
|
|
* next paragraph). This allows applications to optionally function even when their Siteminder infrastructure is
|
|
* unavailable, as is often the case during development.</p>
|
|
* 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}
|
|
* 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>
|
|
* 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>
|
|
* org.acegisecurity.util.FilterToBeanProxy}.</p>
|
|
- *
|
|
|
|
- * @author Scott McCrory
|
|
|
|
- * @version $Id$
|
|
|
|
*/
|
|
*/
|
|
public class SiteminderAuthenticationProcessingFilter extends AuthenticationProcessingFilter {
|
|
public class SiteminderAuthenticationProcessingFilter extends AuthenticationProcessingFilter {
|
|
-
|
|
|
|
//~ Static fields/initializers =====================================================================================
|
|
//~ Static fields/initializers =====================================================================================
|
|
|
|
|
|
/** Log instance for debugging */
|
|
/** Log instance for debugging */
|
|
@@ -56,15 +52,21 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
|
|
|
|
|
|
//~ Instance fields ================================================================================================
|
|
//~ Instance fields ================================================================================================
|
|
|
|
|
|
|
|
+ /** Form password request key. */
|
|
|
|
+ private String formPasswordParameterKey = null;
|
|
|
|
+
|
|
/** Form username request key. */
|
|
/** Form username request key. */
|
|
private String formUsernameParameterKey = null;
|
|
private String formUsernameParameterKey = null;
|
|
|
|
|
|
|
|
+ /** Siteminder password header key. */
|
|
|
|
+ private String siteminderPasswordHeaderKey = null;
|
|
|
|
+
|
|
/** Siteminder username header key. */
|
|
/** Siteminder username header key. */
|
|
private String siteminderUsernameHeaderKey = null;
|
|
private String siteminderUsernameHeaderKey = null;
|
|
|
|
|
|
//~ Constructors ===================================================================================================
|
|
//~ Constructors ===================================================================================================
|
|
|
|
|
|
- /**
|
|
|
|
|
|
+/**
|
|
* Basic constructor.
|
|
* Basic constructor.
|
|
*/
|
|
*/
|
|
public SiteminderAuthenticationProcessingFilter() {
|
|
public SiteminderAuthenticationProcessingFilter() {
|
|
@@ -74,19 +76,24 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
|
|
//~ Methods ========================================================================================================
|
|
//~ Methods ========================================================================================================
|
|
|
|
|
|
/**
|
|
/**
|
|
|
|
+ *
|
|
* @see org.acegisecurity.ui.AbstractProcessingFilter#attemptAuthentication(javax.servlet.http.HttpServletRequest)
|
|
* @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 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);
|
|
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()) {
|
|
if (logger.isDebugEnabled()) {
|
|
logger.debug("Siteminder headers not found for authentication, so trying to use form values");
|
|
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);
|
|
username = request.getParameter(ACEGI_SECURITY_FORM_USERNAME_KEY);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ password = obtainPassword(request);
|
|
}
|
|
}
|
|
|
|
|
|
// Convert username and password to upper case. This is normally not a
|
|
// Convert username and password to upper case. This is normally not a
|
|
@@ -109,9 +117,14 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
|
|
username = "";
|
|
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
|
|
// Allow subclasses to set the "details" property
|
|
setDetails(request, authRequest);
|
|
setDetails(request, authRequest);
|
|
@@ -122,6 +135,15 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
|
|
return this.getAuthenticationManager().authenticate(authRequest);
|
|
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.
|
|
* Returns the form username parameter key.
|
|
*
|
|
*
|
|
@@ -131,6 +153,15 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
|
|
return formUsernameParameterKey;
|
|
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.
|
|
* 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
|
|
* @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
|
|
* @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)
|
|
* javax.servlet.http.HttpServletResponse)
|
|
*/
|
|
*/
|
|
protected boolean requiresAuthentication(final HttpServletRequest request, final HttpServletResponse response) {
|
|
protected boolean requiresAuthentication(final HttpServletRequest request, final HttpServletResponse response) {
|
|
-
|
|
|
|
String uri = request.getRequestURI();
|
|
String uri = request.getRequestURI();
|
|
int pathParamIndex = uri.indexOf(';');
|
|
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()
|
|
//attempt authentication if j_secuity_check is present or if the getDefaultTargetUrl()
|
|
//is present and user is not already authenticated.
|
|
//is present and user is not already authenticated.
|
|
boolean bAuthenticated = false;
|
|
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) {
|
|
if (context != null) {
|
|
Authentication auth = context.getAuthentication();
|
|
Authentication auth = context.getAuthentication();
|
|
@@ -186,7 +222,7 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
|
|
|
|
|
|
// if true is returned then authentication will be attempted.
|
|
// if true is returned then authentication will be attempted.
|
|
boolean bAttemptAuthentication = (uri.endsWith(request.getContextPath() + getFilterProcessesUrl()))
|
|
boolean bAttemptAuthentication = (uri.endsWith(request.getContextPath() + getFilterProcessesUrl()))
|
|
- || ((getDefaultTargetUrl() != null) && uri.endsWith(getDefaultTargetUrl()) && !bAuthenticated);
|
|
|
|
|
|
+ || ((getDefaultTargetUrl() != null) && uri.endsWith(getDefaultTargetUrl()) && !bAuthenticated);
|
|
|
|
|
|
if (logger.isDebugEnabled()) {
|
|
if (logger.isDebugEnabled()) {
|
|
logger.debug("Authentication attempted for the following URI ==> " + uri + " is " + bAttemptAuthentication);
|
|
logger.debug("Authentication attempted for the following URI ==> " + uri + " is " + bAttemptAuthentication);
|
|
@@ -195,6 +231,15 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
|
|
return bAttemptAuthentication;
|
|
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.
|
|
* Sets the form username parameter key.
|
|
*
|
|
*
|
|
@@ -204,6 +249,15 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
|
|
this.formUsernameParameterKey = key;
|
|
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.
|
|
* Sets the Siteminder username header key.
|
|
*
|
|
*
|