diff --git a/core/src/main/java/org/acegisecurity/ui/webapp/SiteminderAuthenticationProcessingFilter.java b/core/src/main/java/org/acegisecurity/ui/webapp/SiteminderAuthenticationProcessingFilter.java new file mode 100644 index 0000000000..5a036b0bb5 --- /dev/null +++ b/core/src/main/java/org/acegisecurity/ui/webapp/SiteminderAuthenticationProcessingFilter.java @@ -0,0 +1,260 @@ +package net.sf.acegisecurity.ui.webapp; + +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +import net.sf.acegisecurity.Authentication; +import net.sf.acegisecurity.AuthenticationException; +import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; +import net.sf.acegisecurity.ui.WebAuthenticationDetails; + +/** + * Extends Acegi's AuthenticationProcessingFilter to use Siteminder's headers for identification. + * + *

+ * Provides the ability set all source key names and also provides form-based authentication as a backup. + *

+ * + *

+ * You must set the Siteminder header keys, otherwise Siteminder checks will be skipped (there + * are no defaults). If the Siteminder check is unsuccessful or if the headers are not + * defined/found in the HTTP request, then the form parameters will be checked (see below). + * This allows applications to function even when their Siteminder infrastructure + * is unavailable, as is often the case during development. If you do not wish to use backup + * form-based authentication, then set the form parameter keys to null/blank. + *

+ * + *

+ * Siteminder must present at least one HTTP header to this filter - typically + * containing a unique identifier such a username, an employee number or a national ID. + * This makes sense because Siteminder has already authenticated the user prior to + * getting to this filter, so we're really only using it for identification and not authentication. + * Set the siteminderUsernameHeaderKey value to tell the filter where to greb the "username" + * value. You'll typically also set the siteminderPasswordHeaderKey to the same header key. + * Just remember to modify your AuthenticationDAO so that it can handle identity-only requests! * + *

+ * + *

+ * Forms must present two parameters to this filter: a username and a password. + * If not specified, the parameter names to use are defaulted to the static fields + * {@link #ACEGI_SECURITY_FORM_USERNAME_KEY} and {@link #ACEGI_SECURITY_FORM_PASSWORD_KEY}. + *

+ * + *

+ * Do not use this class directly. Instead, configure web.xml + * to use the {@link net.sf.acegisecurity.util.FilterChainProxy} and include this filter. + *

+ * + * @author Scott McCrory + * @author Ben Alex + * @since 0.9.0 + * @version CVS $Id$ + */ +public class SiteminderAuthenticationProcessingFilter extends AuthenticationProcessingFilter { + + /** + * Siteminder username header key. + */ + private String siteminderUsernameHeaderKey = null; + + /** + * Siteminder password header key. + */ + private String siteminderPasswordHeaderKey = null; + + /** + * Form username request key. + */ + private String formUsernameParameterKey = null; + + /** + * Form password request key. + */ + private String formPasswordParameterKey = null; + + /** + * Basic constructor. + */ + public SiteminderAuthenticationProcessingFilter() { + super(); + } + + /*** + * This filter by default responds to /j_acegi_security_check. + * + * @return the default + */ + public String getDefaultFilterProcessesUrl() { + return "/j_acegi_security_check"; + } + + public Authentication attemptAuthentication(HttpServletRequest request) throws AuthenticationException { + + String username = null; + String password = null; + + // 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 authentication info wasn't available, then get it from the form parameters + if (username == null || username.length() == 0 || password == null || password.length() == 0) { + + //System.out.println("Siteminder headers not found for authentication"); + + if (formUsernameParameterKey != null && formUsernameParameterKey.length() > 0) { + username = request.getParameter(formUsernameParameterKey); + } + else { + username = request.getParameter(ACEGI_SECURITY_FORM_USERNAME_KEY); + } + + password = obtainPassword(request); + + } + + // If either are null, set them to blank to avoid a NPE. + if (username == null) { + username = ""; + } + if (password == null) { + password = ""; + } + + UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); + + // Allow subclasses to set the "details" property + setDetails(request, authRequest); + + // Place the last username attempted into HttpSession for views + request.getSession().setAttribute(ACEGI_SECURITY_LAST_USERNAME_KEY, username); + + return this.getAuthenticationManager().authenticate(authRequest); + } + + public void init(FilterConfig filterConfig) throws ServletException { + } + + /*** + * Provided so that subclasses may configure what is put into the + * authentication request's details property. The default implementation + * simply constructs {@link WebAuthenticationDetails}. + * + * @param request that an authentication request is being created for + * @param authRequest the authentication request object that should have + * its details set + */ + protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) { + authRequest.setDetails(new WebAuthenticationDetails(request)); + } + + /*** + * Enables subclasses to override the composition of the password, such as + * by including additional values and a separator. + * + *

+ * This might be used for example if a postcode/zipcode was required in + * addition to the password. A delimiter such as a pipe (|) should be used + * to separate the password and extended value(s). The + * AuthenticationDao will need to generate the expected + * password in a corresponding manner. + *

+ * + * @param request so that request attributes can be retrieved + * + * @return the password that will be presented in the + * Authentication request token to the + * AuthenticationManager + */ + protected String obtainPassword(HttpServletRequest request) { + + if (formPasswordParameterKey != null && formPasswordParameterKey.length() > 0) { + return request.getParameter(formPasswordParameterKey); + } + else { + return request.getParameter(ACEGI_SECURITY_FORM_PASSWORD_KEY); + } + + } + + /** + * Returns the form password parameter key. + * + * @return The form password parameter key. + */ + public String getFormPasswordParameterKey() { + return formPasswordParameterKey; + } + + /** + * Returns the form username parameter key. + * + * @return The form username parameter key. + */ + public String getFormUsernameParameterKey() { + 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. + * + * @return The Siteminder username header key. + */ + public String getSiteminderUsernameHeaderKey() { + return siteminderUsernameHeaderKey; + } + + /** + * 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. + * + * @param key The form username parameter key. + */ + public void setFormUsernameParameterKey(final String 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. + * + * @param key The Siteminder username header key. + */ + public void setSiteminderUsernameHeaderKey(final String key) { + this.siteminderUsernameHeaderKey = key; + } + +}