FORM based authentication is tested and functional, will test BASIC and make any needed fixes soon
--- /dev/null
+/*
+ * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/authenticator/Authenticator.java,v 1.1 2003/07/07 13:12:56 maxcooper Exp $
+ * $Revision: 1.1 $
+ * $Date: 2003/07/07 13:12:56 $
+ *
+ * ====================================================================
+ * The SecurityFilter Software License, Version 1.1
+ *
+ * (this license is derived and fully compatible with the Apache Software
+ * License - see http://www.apache.org/LICENSE.txt)
+ *
+ * Copyright (c) 2002 SecurityFilter.org. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by
+ * SecurityFilter.org (http://www.securityfilter.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The name "SecurityFilter" must not be used to endorse or promote
+ * products derived from this software without prior written permission.
+ * For written permission, please contact license@securityfilter.org .
+ *
+ * 5. Products derived from this software may not be called "SecurityFilter",
+ * nor may "SecurityFilter" appear in their name, without prior written
+ * permission of SecurityFilter.org.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE SECURITY FILTER PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ */
+
+package org.securityfilter.authenticator;
+
+import org.securityfilter.config.SecurityConfig;
+import org.securityfilter.filter.*;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.http.*;
+import java.io.IOException;
+
+/**
+ * Authenticator - interface for a SecurityFilter authenticator module. Implementations correspond to an implementation
+ * method, such as FORM or BASIC (others are possible).
+ *
+ * @author Max Cooper (max@maxcooper.com)
+ * @version $Revision: 1.1 $ $Date: 2003/07/07 13:12:56 $
+ */
+public interface Authenticator {
+
+ /**
+ * Initialize this Authenticator.
+ *
+ * @param filterConfig
+ * @param securityConfig
+ */
+ public void init(FilterConfig filterConfig, SecurityConfig securityConfig) throws Exception;
+
+ /**
+ * Get the auth method string for this authentication scheme.
+ *
+ * @return the auth method string for this Authenticator
+ */
+ public String getAuthMethod();
+
+ /**
+ * Process any login information that was included in the request, if any.
+ * Returns true if SecurityFilter should abort further processing after the method completes (for example, if a
+ * redirect was sent as part of the login processing).
+ *
+ * @param request
+ * @param response
+ * @return true if the filter should return after this method ends, false otherwise
+ */
+ public boolean processLogin(SecurityRequestWrapper request, HttpServletResponse response) throws Exception;
+
+ /**
+ * Show the login interface.
+ *
+ * @param request
+ * @param response
+ */
+ public void showLogin(HttpServletRequest request, HttpServletResponse response) throws IOException;
+
+ /**
+ * Return true if security checks should be bypassed for this request.
+ *
+ * Example: for FORM based authentication, the login and error pages should always be viewable without being
+ * authenticated, even if they would otherwise be blocked by a security constraint.
+ *
+ * @param request
+ * @return true if security should be bypassed, false otherwise
+ */
+ public boolean bypassSecurityForThisRequest(
+ SecurityRequestWrapper request,
+ URLPatternMatcher patternMatcher
+ ) throws Exception;
+}
+
+// ------------------------------------------------------------------------
+// EOF
--- /dev/null
+/*
+ * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/authenticator/AuthenticatorFactory.java,v 1.1 2003/07/07 13:12:56 maxcooper Exp $
+ * $Revision: 1.1 $
+ * $Date: 2003/07/07 13:12:56 $
+ *
+ * ====================================================================
+ * The SecurityFilter Software License, Version 1.1
+ *
+ * (this license is derived and fully compatible with the Apache Software
+ * License - see http://www.apache.org/LICENSE.txt)
+ *
+ * Copyright (c) 2002 SecurityFilter.org. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by
+ * SecurityFilter.org (http://www.securityfilter.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The name "SecurityFilter" must not be used to endorse or promote
+ * products derived from this software without prior written permission.
+ * For written permission, please contact license@securityfilter.org .
+ *
+ * 5. Products derived from this software may not be called "SecurityFilter",
+ * nor may "SecurityFilter" appear in their name, without prior written
+ * permission of SecurityFilter.org.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE SECURITY FILTER PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ */
+
+package org.securityfilter.authenticator;
+
+import org.securityfilter.config.SecurityConfig;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * AuthenticatorFactory - this class will create Authenticator instance.
+ *
+ * It is designed to be easy to extend to add more Authenticator implementations, or to allow custom Authenticators to
+ * be specified in the config file and created here in this factory class.
+ *
+ * @author Max Cooper (max@maxcooper.com)
+ * @version $Revision: 1.1 $ $Date: 2003/07/07 13:12:56 $
+ */
+public class AuthenticatorFactory {
+
+ /**
+ * Create an Authenticator based on the specified configuration information.
+ *
+ * @param filterConfig
+ * @param securityConfig
+ * @return
+ * @throws Exception
+ */
+ public static Authenticator createAuthenticator(
+ FilterConfig filterConfig,
+ SecurityConfig securityConfig
+ ) throws Exception {
+ Authenticator authenticator = null;
+
+ String authMethod = securityConfig.getAuthMethod();
+ if (HttpServletRequest.FORM_AUTH.equals(authMethod)) {
+ // FORM
+ authenticator = new FormAuthenticator();
+ } else if (HttpServletRequest.BASIC_AUTH.equals(authMethod)) {
+ // BASIC
+ authenticator = new BasicAuthenticator();
+ } else {
+ throw new Exception("No Authenticator available for auth method: " + authMethod);
+ }
+ authenticator.init(filterConfig, securityConfig);
+ return authenticator;
+ }
+}
+
+// ------------------------------------------------------------------------
+// EOF
--- /dev/null
+/*
+ * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/authenticator/BasicAuthenticator.java,v 1.1 2003/07/07 13:12:56 maxcooper Exp $
+ * $Revision: 1.1 $
+ * $Date: 2003/07/07 13:12:56 $
+ *
+ * ====================================================================
+ * The SecurityFilter Software License, Version 1.1
+ *
+ * (this license is derived and fully compatible with the Apache Software
+ * License - see http://www.apache.org/LICENSE.txt)
+ *
+ * Copyright (c) 2002 SecurityFilter.org. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by
+ * SecurityFilter.org (http://www.securityfilter.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The name "SecurityFilter" must not be used to endorse or promote
+ * products derived from this software without prior written permission.
+ * For written permission, please contact license@securityfilter.org .
+ *
+ * 5. Products derived from this software may not be called "SecurityFilter",
+ * nor may "SecurityFilter" appear in their name, without prior written
+ * permission of SecurityFilter.org.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE SECURITY FILTER PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ */
+
+package org.securityfilter.authenticator;
+
+import org.apache.commons.codec.binary.Base64;
+import org.securityfilter.config.SecurityConfig;
+import org.securityfilter.filter.*;
+import org.securityfilter.realm.SecurityRealmInterface;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.http.*;
+import java.io.IOException;
+import java.security.Principal;
+
+/**
+ * BasicAuthenticator - authenticator implementation for the BASIC auth method.
+ *
+ * @author Daya Sharma (iamdaya@yahoo.com, billydaya@sbcglobal.net)
+ * @author Max Cooper (max@maxcooper.com)
+ * @version $Revision: 1.1 $ $Date: 2003/07/07 13:12:56 $
+ */
+public class BasicAuthenticator implements Authenticator {
+ public static final String BASIC_WINDOW_SHOWN = "basic_window_shown";
+ public static final String LOGIN_ATTEMPTS = "loginAttempts";
+ protected static final String DUMMY_TOKEN = "dummyToken";
+
+ public static final Base64 base64Helper = new Base64();
+
+ protected String tooManyIncorrectLogins;
+
+ protected SecurityRealmInterface realm;
+
+ /**
+ * Initialize this Authenticator.
+ *
+ * @param filterConfig
+ * @param securityConfig
+ */
+ public void init(FilterConfig filterConfig, SecurityConfig securityConfig) throws Exception {
+ realm = securityConfig.getRealm();
+ tooManyIncorrectLogins = "Sorry you are having problems logging in, please try again";
+ }
+
+ /**
+ * Returns BASIC as the authentication method.
+ *
+ * @return BASIC
+ */
+ public String getAuthMethod() {
+ return HttpServletRequest.BASIC_AUTH;
+ }
+
+ /**
+ * Process any login information that was included in the request, if any.
+ * Returns true if SecurityFilter should abort further processing after the method completes (for example, if a
+ * redirect was sent as part of the login processing).
+ *
+ * @param request
+ * @param response
+ * @return true if the filter should return after this method ends, false otherwise
+ */
+ public boolean processLogin(SecurityRequestWrapper request, HttpServletResponse response) throws Exception {
+ if (basicAuthentication(request)) {
+ request.getSession().removeAttribute(BASIC_WINDOW_SHOWN);
+ String username = parseUsername(request.getHeader("Authorization"));
+ String password = parsePassword(request.getHeader("Authorization"));
+ Principal principal = realm.authenticate(username, password);
+ if (principal != null) {
+ // login successful
+ // invalidate old session if the user was already authenticated
+ // NOTE: we may want to check if the user re-authenticated as the same user, currently
+ // the session will be invalidated even if the user authenticates as the same user.
+ request.setUserPrincipal(principal);
+ String continueToURL = SecurityFilter.getContinueToURL(request);
+ request.getSession().setAttribute(DUMMY_TOKEN, DUMMY_TOKEN);
+ // This is the url that the user was initially accessing before being prompted for login.
+ response.sendRedirect(response.encodeRedirectURL(continueToURL));
+ } else {
+ // login failed
+ // show the basic authentication window again.
+ showLogin(request.getCurrentRequest(), response);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if this request includes BASIC auth info.
+ *
+ * @param request
+ * @return
+ */
+ private boolean basicAuthentication(HttpServletRequest request) {
+ return (
+ request.getSession().getAttribute(BASIC_WINDOW_SHOWN) != null
+ && request.getHeader("Authorization") != null
+ );
+ }
+
+ /**
+ * Parse the username out of the BASIC authorization header string.
+ * @param authorization
+ * @return
+ */
+ private String parseUsername(String authorization) {
+ String unencoded = decodeBasicAuthorizationString(authorization);
+ if (unencoded == null) {
+ return null;
+ } else {
+ int colon = unencoded.indexOf(':');
+ if (colon < 0) {
+ return null;
+ } else {
+ return unencoded.substring(0, colon).trim();
+ }
+ }
+ }
+
+ /**
+ * Parse the password out of the BASIC authorization header string.
+ * @param authorization
+ * @return
+ */
+ private String parsePassword(String authorization) {
+ String unencoded = decodeBasicAuthorizationString(authorization);
+ if (unencoded == null) {
+ return null;
+ } else {
+ int colon = unencoded.indexOf(':');
+ if (colon < 0) {
+ return (null);
+ } else {
+ return unencoded.substring(colon + 1).trim();
+ }
+ }
+ }
+
+ /**
+ * Decode the BASIC authorization string.
+ *
+ * @param authorization
+ * @return
+ */
+ private String decodeBasicAuthorizationString(String authorization) {
+ if (authorization == null || !authorization.toLowerCase().startsWith("basic ")) {
+ return null;
+ } else {
+ authorization = authorization.substring(6).trim();
+ // Decode and parse the authorization credentials
+ return new String(base64Helper.decodeBase64(authorization.getBytes()));
+ }
+ }
+
+ /**
+ * Show the login page.
+ *
+ * @param request the current request
+ * @param response the current response
+ */
+ public void showLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
+ // save this request
+ SecurityFilter.saveRequestInformation(request);
+
+ // redirect to login page
+ request.getSession().setAttribute(BASIC_WINDOW_SHOWN, "shown");
+ int loginAttempts = 1;
+ if (request.getSession().getAttribute(LOGIN_ATTEMPTS) != null) {
+ loginAttempts = ((Integer) request.getSession().getAttribute(LOGIN_ATTEMPTS)).intValue();
+ loginAttempts += 1;
+ }
+ // todo: we can put some useful message here, perhaps a internationlizable format of message.
+ String loginAttemptMessage = "Login attempt number " + loginAttempts;
+ String logo;
+ if (loginAttempts <= 3) {
+ String realm = String.valueOf(Math.random());
+ if (loginAttempts < 2) {
+ logo = "Basic Auth with Security Filter";
+ } else {
+ logo = loginAttemptMessage;
+ }
+ String blankLine = " ";
+ logo = blankLine + blankLine + blankLine + logo + blankLine + blankLine;
+ System.err.println("response.setHeader \"WWW-Authenticate\", \"BASIC realm=\"" + logo + realm + "\"");
+ response.setHeader("WWW-Authenticate", "BASIC realm=\"" + realm + logo + "\"");
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ request.getSession().setAttribute(LOGIN_ATTEMPTS, new Integer(loginAttempts));
+ } else {
+ request.getSession().removeAttribute(LOGIN_ATTEMPTS);
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED, tooManyIncorrectLogins);
+ }
+ }
+
+ /**
+ * All requests should be subject to security checking for BASIC authentication.
+ *
+ * @param request
+ * @return always false -- check all requests
+ */
+ public boolean bypassSecurityForThisRequest(SecurityRequestWrapper request, URLPatternMatcher patternMatcher) {
+ return false;
+ }
+}
+
+// ------------------------------------------------------------------------
+// EOF
--- /dev/null
+/*
+ * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/authenticator/FormAuthenticator.java,v 1.1 2003/07/07 13:12:56 maxcooper Exp $
+ * $Revision: 1.1 $
+ * $Date: 2003/07/07 13:12:56 $
+ *
+ * ====================================================================
+ * The SecurityFilter Software License, Version 1.1
+ *
+ * (this license is derived and fully compatible with the Apache Software
+ * License - see http://www.apache.org/LICENSE.txt)
+ *
+ * Copyright (c) 2002 SecurityFilter.org. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by
+ * SecurityFilter.org (http://www.securityfilter.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The name "SecurityFilter" must not be used to endorse or promote
+ * products derived from this software without prior written permission.
+ * For written permission, please contact license@securityfilter.org .
+ *
+ * 5. Products derived from this software may not be called "SecurityFilter",
+ * nor may "SecurityFilter" appear in their name, without prior written
+ * permission of SecurityFilter.org.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE SECURITY FILTER PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ */
+
+package org.securityfilter.authenticator;
+
+import org.securityfilter.config.SecurityConfig;
+import org.securityfilter.filter.*;
+import org.securityfilter.realm.SecurityRealmInterface;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.http.*;
+import java.io.IOException;
+import java.security.Principal;
+
+/**
+ * FormAuthenticator - authenticator implementation for the FORM auth method.
+ *
+ * @author Max Cooper (max@maxcooper.com)
+ * @version $Revision: 1.1 $ $Date: 2003/07/07 13:12:56 $
+ */
+public class FormAuthenticator implements Authenticator {
+
+ public static final String LOGIN_SUBMIT_PATTERN_KEY = "loginSubmitPattern";
+ public static final String DEFAULT_LOGIN_SUBMIT_PATTERN = "/j_security_check";
+ protected String loginSubmitPattern;
+
+ protected static final String FORM_USERNAME = "j_username";
+ protected static final String FORM_PASSWORD = "j_password";
+
+ protected String loginPage;
+ protected URLPattern loginPagePattern;
+
+ protected String errorPage;
+ protected URLPattern errorPagePattern;
+
+ protected String defaultPage;
+
+ protected SecurityRealmInterface realm;
+
+ /**
+ * Initilize this Authenticator.
+ *
+ * @param filterConfig
+ * @param securityConfig
+ */
+ public void init(FilterConfig filterConfig, SecurityConfig securityConfig) throws Exception {
+
+ realm = securityConfig.getRealm();
+
+ // login submit pattern
+ loginSubmitPattern = filterConfig.getInitParameter(LOGIN_SUBMIT_PATTERN_KEY);
+ if (loginSubmitPattern == null) {
+ loginSubmitPattern = DEFAULT_LOGIN_SUBMIT_PATTERN;
+ }
+
+ // default page
+ defaultPage = securityConfig.getDefaultPage();
+
+ URLPatternFactory patternFactory = new URLPatternFactory();
+
+ // login page
+ loginPage = securityConfig.getLoginPage();
+ loginPagePattern = patternFactory.createURLPattern(loginPage, null, null, 0);
+
+ // error page
+ errorPage = securityConfig.getErrorPage();
+ errorPagePattern = patternFactory.createURLPattern(errorPage, null, null, 0);
+ }
+
+ /**
+ * Returns FORM as the authentication method.
+ *
+ * @return FORM
+ */
+ public String getAuthMethod() {
+ return HttpServletRequest.FORM_AUTH;
+ }
+
+ /**
+ * Process any login information that was included in the request, if any.
+ * Returns true if SecurityFilter should abort further processing after the method completes (for example, if a
+ * redirect was sent as part of the login processing).
+ *
+ * @param request
+ * @param response
+ * @return true if the filter should return after this method ends, false otherwise
+ */
+ public boolean processLogin(SecurityRequestWrapper request, HttpServletResponse response) throws Exception {
+ if (request.getMatchableURL().endsWith(loginSubmitPattern)) {
+ String username = request.getParameter(FORM_USERNAME);
+ String password = request.getParameter(FORM_PASSWORD);
+ Principal principal = realm.authenticate(username, password);
+ if (principal != null) {
+ // login successful
+ // invalidate old session if the user was already authenticated
+ // NOTE: we may want to check if the user re-authenticated as the same user, currently
+ // the session will be invalidated even if the user authenticates as the same user.
+ request.setUserPrincipal(principal);
+ String continueToURL = getContinueToURL(request);
+ // This is the url that the user was initially accessing before being prompted for login.
+ response.sendRedirect(response.encodeRedirectURL(continueToURL));
+ } else {
+ // login failed
+ // set response status and forward to error page
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ request.getRequestDispatcher(errorPage).forward(request, response);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Show the login page.
+ *
+ * @param request the current request
+ * @param response the current response
+ */
+ public void showLogin(
+ HttpServletRequest request,
+ HttpServletResponse response
+ ) throws IOException {
+ // save this request
+ SecurityFilter.saveRequestInformation(request);
+
+ // redirect to login page
+ response.sendRedirect(request.getContextPath() + loginPage);
+ return;
+ }
+
+ /**
+ * FormAuthenticator has a special case where the user should be sent to a default page if the user
+ * spontaneously submits a login request.
+ *
+ * @param request
+ * @return a URL to send the user to after logging in
+ */
+ private String getContinueToURL(HttpServletRequest request) {
+ String savedURL = SecurityFilter.getContinueToURL(request);
+ if (savedURL != null) {
+ return savedURL;
+ } else {
+ return request.getContextPath() + defaultPage;
+ }
+ }
+
+ /**
+ * The login and error pages should be viewable, even if they would otherwise be blocked by a security constraint.
+ *
+ * @param request
+ * @return
+ */
+ public boolean bypassSecurityForThisRequest(
+ SecurityRequestWrapper request,
+ URLPatternMatcher patternMatcher
+ ) throws Exception {
+ String requestURL = request.getMatchableURL();
+ return patternMatcher.match(requestURL, loginPagePattern) || patternMatcher.match(requestURL, errorPagePattern);
+ }
+}
+
+// ------------------------------------------------------------------------
+// EOF
/*
- * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/filter/SecurityFilter.java,v 1.20 2003/07/07 04:18:29 maxcooper Exp $
- * $Revision: 1.20 $
- * $Date: 2003/07/07 04:18:29 $
+ * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/filter/SecurityFilter.java,v 1.21 2003/07/07 13:12:57 maxcooper Exp $
+ * $Revision: 1.21 $
+ * $Date: 2003/07/07 13:12:57 $
*
* ====================================================================
* The SecurityFilter Software License, Version 1.1
package org.securityfilter.filter;
-import org.apache.commons.codec.binary.Base64;
-import org.securityfilter.config.AuthConstraint;
-import org.securityfilter.config.SecurityConfig;
-import org.securityfilter.config.SecurityConstraint;
-import org.securityfilter.config.WebResourceCollection;
+import org.securityfilter.authenticator.*;
+import org.securityfilter.config.*;
import org.securityfilter.realm.SecurityRealmInterface;
import javax.servlet.*;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
+import javax.servlet.http.*;
import java.io.IOException;
import java.net.URL;
import java.security.Principal;
* @author Max Cooper (max@maxcooper.com)
* @author Daya Sharma (iamdaya@yahoo.com, billydaya@sbcglobal.net)
* @author Torgeir Veimo (torgeir@pobox.com)
- * @version $Revision: 1.20 $ $Date: 2003/07/07 04:18:29 $
+ * @version $Revision: 1.21 $ $Date: 2003/07/07 13:12:57 $
*/
public class SecurityFilter implements Filter {
public static final String CONFIG_FILE_KEY = "config";
public static final String DEFAULT_CONFIG_FILE = "/WEB-INF/securityfilter-config.xml";
-
public static final String VALIDATE_KEY = "validate";
- public static final String LOGIN_SUBMIT_PATTERN_KEY = "loginSubmitPattern";
- public static final String DEFAULT_LOGIN_SUBMIT_PATTERN = "/j_security_check";
- protected String loginSubmitPattern;
-
public static final String TRUE = "true";
- public static final String SAVED_REQUEST_URL = SecurityFilter.class.getName() + ".SAVED_REQUEST_URL";
- public static final String SAVED_REQUEST = SecurityFilter.class.getName() + ".SAVED_REQUEST";
public static final String ALREADY_PROCESSED = SecurityFilter.class.getName() + ".ALREADY_PROCESSED";
- public static final String BASIC_WINDOW_SHOWN = "basic_window_shown";
- public static final String LOGIN_ATTEMPTS = "loginAttempts";
-
- protected static final String DUMMY_TOKEN = "dummyToken";
-
- protected static final String FORM_USERNAME = "j_username";
- protected static final String FORM_PASSWORD = "j_password";
-
- public static final Base64 base64Helper = new Base64();
+ public static final String SAVED_REQUEST_URL = SecurityFilter.class.getName() + ".SAVED_REQUEST_URL";
+ public static final String SAVED_REQUEST = SecurityFilter.class.getName() + ".SAVED_REQUEST";
protected FilterConfig config;
protected SecurityRealmInterface realm;
- protected String loginPage;
- protected URLPattern loginPagePattern;
- protected String errorPage;
- protected URLPattern errorPagePattern;
- protected String defaultPage;
- protected URLPatternFactory patternFactory;
protected List patternList;
-
- protected String authMethod;
- protected boolean basic = false;
- protected String tooManyIncorrectLogins;
+ protected URLPatternFactory patternFactory;
+ protected Authenticator authenticator;
/**
* Perform filtering operation, and optionally pass the request down the chain.
// get a URLPatternMatcher to use for this thread
URLPatternMatcher patternMatcher = patternFactory.createURLPatternMatcher();
- // get the part of the URL to check for matches
- String requestURL = getMatchableURL(hReq);
-
// get saved request, if any (returns null if not applicable)
SavedRequest savedRequest = getSavedRequest(hReq);
// wrap request
- wrappedRequest = new SecurityRequestWrapper(hReq, realm, savedRequest);
+ wrappedRequest = new SecurityRequestWrapper(hReq, savedRequest, realm, authenticator.getAuthMethod());
URLPattern match = null;
try {
- // check if this is a login form submittal
- if (basicAuthentication(hReq)) {
- hReq.getSession().removeAttribute(BASIC_WINDOW_SHOWN);
- processLogin(wrappedRequest, hRes);
- return;
- } else if (requestURL.endsWith(loginSubmitPattern)) {
- processLogin(wrappedRequest, hRes);
+ // check if this request includes login info
+ if (authenticator.processLogin(wrappedRequest, hRes)) {
return;
}
- // only check the request for a security constraint match if it doesn't
- // match the login page or error page patterns -- this allows requests for the
- // login page and error pages to be viewed even when their URLs would otherwise
- // be subject to a security constraint
- if (
- !patternMatcher.match(requestURL, loginPagePattern)
- && !patternMatcher.match(requestURL, errorPagePattern)
- ) {
+ // match the url if the authenticator does not indicate that security should be bypassed
+ if (!authenticator.bypassSecurityForThisRequest(wrappedRequest, patternMatcher)) {
// check if request matches security constraint
- match = matchPattern(requestURL, wrappedRequest.getMethod(), patternMatcher);
+ match = matchPattern(wrappedRequest.getMatchableURL(), wrappedRequest.getMethod(), patternMatcher);
}
} catch (Exception e) {
throw new ServletException("Error matching patterns", e);
Collection roles = authConstraint.getRoles();
Principal principal = wrappedRequest.getUserPrincipal();
// if roles is empty, access will be blocked no matter who the user is, so skip the login
- if (!roles.isEmpty() && principal == null && hReq.getSession().getAttribute(DUMMY_TOKEN) == null) {
+ // todo: do we still need this DUMMY_TOKEN check for BASIC auth?
+ if (!roles.isEmpty() && principal == null /* && hReq.getSession().getAttribute(DUMMY_TOKEN) == null */) {
// user needs to be authenticated
- showLogin(hReq, hRes);
+ authenticator.showLogin(hReq, hRes);
return;
} else {
boolean authorized = false;
chain.doFilter(request, response);
}
- private boolean basicAuthentication(HttpServletRequest hReq) {
- return (
- authMethod.equalsIgnoreCase("basic")
- && hReq.getSession().getAttribute(BASIC_WINDOW_SHOWN) != null
- && hReq.getHeader("Authorization") != null
- );
- }
-
/**
* Initialize the SecurityFilter.
*
public void init(FilterConfig config) throws ServletException {
this.config = config;
try {
- patternFactory = new URLPatternFactory();
-
// parse config file
+
// config file name
String configFile = config.getInitParameter(CONFIG_FILE_KEY);
if (configFile == null) {
configFile = DEFAULT_CONFIG_FILE;
}
URL configURL = config.getServletContext().getResource(configFile);
+
// validate config file?
- String validate = config.getInitParameter(VALIDATE_KEY);
- // login submit pattern
- loginSubmitPattern = config.getInitParameter(LOGIN_SUBMIT_PATTERN_KEY);
- if (loginSubmitPattern == null) {
- loginSubmitPattern = DEFAULT_LOGIN_SUBMIT_PATTERN;
- }
- SecurityConfig securityConfig = new SecurityConfig(TRUE.equalsIgnoreCase(validate));
+ boolean validate = TRUE.equalsIgnoreCase(config.getInitParameter(VALIDATE_KEY));
+
+ SecurityConfig securityConfig = new SecurityConfig(validate);
securityConfig.loadConfig(configURL);
- // get config values
+ // get the realm
realm = securityConfig.getRealm();
- defaultPage = securityConfig.getDefaultPage();
-
- // get login and error page patterns
- loginPage = securityConfig.getLoginPage();
- loginPagePattern = patternFactory.createURLPattern(loginPage, null, null, 0);
- errorPage = securityConfig.getErrorPage();
- errorPagePattern = patternFactory.createURLPattern(errorPage, null, null, 0);
- authMethod = securityConfig.getAuthMethod();
- // todo: support DIGEST and CERT authentication schemes.
- if (authMethod.equalsIgnoreCase(HttpServletRequest.BASIC_AUTH)) {
- basic = true;
- }
+
+ // create an Authenticator
+ authenticator = AuthenticatorFactory.createAuthenticator(config, securityConfig);
// create pattern list
+ patternFactory = new URLPatternFactory();
patternList = new ArrayList();
int order = 1;
List constraints = securityConfig.getSecurityConstraints();
}
/**
- * Set the filter configuration, included for WebLogic 6 compatibility.
- *
- * @param config filter configuration object
- */
- public void setFilterConfig(FilterConfig config) throws ServletException {
- init(config);
- }
-
- /**
- * Get the filter config object, included for WebLogic 6 compatibility.
- */
- public FilterConfig getFilterConfig() {
- return config;
- }
-
- /**
* Find a match for the requested pattern & method, if any.
*
* @param pattern the pattern to match
}
/**
- * Show the login page.
- *
- * @param request the current request
- * @param response the current response
- * @exception IOException
- * @exception ServletException
- */
- protected void showLogin(
- HttpServletRequest request,
- HttpServletResponse response
- ) throws IOException, ServletException {
- // save this request
- saveRequestInformation(request);
-
- // redirect to login page
- if (basic) {
- request.getSession().setAttribute(BASIC_WINDOW_SHOWN, "shown");
- int loginAttempts = 1;
- if (request.getSession().getAttribute(LOGIN_ATTEMPTS) != null) {
- loginAttempts = ((Integer) request.getSession().getAttribute(LOGIN_ATTEMPTS)).intValue();
- loginAttempts += 1;
- }
- // todo: we can put some useful message here, perhaps a internationlizable format of message.
- tooManyIncorrectLogins = "Sorry you are having problems logging in, please try again";
- String loginAttemptMessage = "Login attempt number " + loginAttempts;
- String logo;
- if (loginAttempts <= 3) {
- String realm = String.valueOf(Math.random());
- if (loginAttempts < 2) {
- logo = "Basic Auth with Security Filter";
- } else {
- logo = loginAttemptMessage;
- }
- String blankLine = " ";
- logo = blankLine + blankLine + blankLine + logo + blankLine + blankLine;
- System.err.println("response.setHeader \"WWW-Authenticate\", \"BASIC realm=\"" + logo + realm + "\"");
- response.setHeader("WWW-Authenticate", "BASIC realm=\"" + realm + logo + "\"");
- response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
- request.getSession().setAttribute(LOGIN_ATTEMPTS, new Integer(loginAttempts));
- } else {
- request.getSession().removeAttribute(LOGIN_ATTEMPTS);
- response.sendError(HttpServletResponse.SC_UNAUTHORIZED, tooManyIncorrectLogins);
- }
- } else {
- response.sendRedirect(request.getContextPath() + loginPage);
- return;
- }
- }
-
- /**
- * Process a login form submittal.
- *
- * @param request the current request
- * @param response the current response
- * @exception IOException
- * @exception ServletException
- */
- protected void processLogin(
- SecurityRequestWrapper request,
- HttpServletResponse response
- ) throws IOException, ServletException {
- String username;
- String password;
- if (basic) {
- username = parseUsername(request.getHeader("Authorization"));
- password = parsePassword(request.getHeader("Authorization"));
- } else {
- username = request.getParameter(FORM_USERNAME);
- password = request.getParameter(FORM_PASSWORD);
- }
- Principal principal = realm.authenticate(username, password);
- if (principal != null) {
- // login successful
- // invalidate old session if the user was already authenticated
- // NOTE: we may want to check if the user re-authenticated as the same user, currently
- // the session will be invalidated even if the user authenticates as the same user.
- request.setUserPrincipal(principal);
- String continueToURL = getContinueToURL(request);
- if (basic) {
- // what does this do?
- request.getSession().setAttribute(DUMMY_TOKEN, DUMMY_TOKEN);
- }
- // This is the url that the user was initially accessing before being prompted for login.
- response.sendRedirect(response.encodeRedirectURL(continueToURL));
- } else {
- // login failed
- if (!basic) {
- // set response status and forward to error page
- response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
- request.getRequestDispatcher(errorPage).forward(request, response);
- } else {
- // show the basic authentication window again.
- showLogin(request.getCurrentRequest(), response);
- }
- }
- }
-
- /**
- * Get the URL to continue to after successful login. This may be the SAVED_REQUEST_URL if the authorization
- * sequence was initiated by the filter, or the default URL (as specified in the config file) if a login
- * request was spontaneously submitted.
- *
- * @param request the current request
- */
- protected String getContinueToURL(HttpServletRequest request) {
- String savedURL = (String) request.getSession().getAttribute(SAVED_REQUEST_URL);
- if (savedURL != null) {
- return savedURL;
- } else {
- return request.getContextPath() + defaultPage;
- }
- }
-
- /**
- * Save request information to re-use when the user is successfully authenticated.
- *
- * @param request the current request
- */
- protected void saveRequestInformation(HttpServletRequest request) {
- HttpSession session = request.getSession();
- session.setAttribute(SecurityFilter.SAVED_REQUEST_URL, getSaveableURL(request));
- session.setAttribute(SecurityFilter.SAVED_REQUEST, new SavedRequest(request));
- }
-
- /**
* If this request matches the one we saved, return the SavedRequest and remove it from the session.
*
* @param request the current request
}
}
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // The following methods are provided as static utilities for use by SecurityFilter and other classes. //
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
/**
- * Return a URL that can be matched against security URL patterns.<p>
+ * Get the URL to continue to after successful login. This may be the SAVED_REQUEST_URL if the authorization
+ * sequence was initiated by the filter, or the default URL (as specified in the config file) if a login
+ * request was spontaneously submitted.
*
- * This is the part after the contextPath, with the pathInfo, but without the query string.<br>
- * http://server:8080/contextPath/someURL.jsp?param=value becomes /someURL.jsp
+ * @param request the current request
+ */
+ public static String getContinueToURL(HttpServletRequest request) {
+ return (String) request.getSession().getAttribute(SAVED_REQUEST_URL);
+ }
+
+ /**
+ * Save request information to re-use when the user is successfully authenticated.
*
- * @param request the request to construct a matchable URL for
+ * @param request the current request
*/
- private String getMatchableURL(HttpServletRequest request) {
- // extract the servlet path portion that needs to be checked
- String matchableURL = request.getServletPath();
- // add the pathInfo, as it needs to be part of the URL we check
- String pathInfo = request.getPathInfo();
- if (pathInfo != null) {
- matchableURL = matchableURL + pathInfo;
- }
- return matchableURL;
+ public static void saveRequestInformation(HttpServletRequest request) {
+ HttpSession session = request.getSession();
+ session.setAttribute(SecurityFilter.SAVED_REQUEST_URL, getSaveableURL(request));
+ session.setAttribute(SecurityFilter.SAVED_REQUEST, new SavedRequest(request));
}
/**
*
* @param request the request to construct a saveable URL for
*/
- private String getSaveableURL(HttpServletRequest request) {
- String url = null;
+ private static String getSaveableURL(HttpServletRequest request) {
StringBuffer saveableURL = null;
- String protocol = request.getProtocol();
try {
saveableURL = request.getRequestURL();
} catch (NoSuchMethodError e) {
- // this is done to support app servers like orion 1.5.2
- // which have not implemented the servlet 2.3 specification but have implemented the final draft of 2.3 spec.
- if (protocol.equals("HTTP/1.1")) { // todo: provide support for ftp, webdav protocol among others.
- if (request.isSecure()) {
- protocol = "https://";
- } else {
- protocol = "http://";
- }
- }
- url = protocol + request.getServerName() + ":" + request.getServerPort() + request.getRequestURI();
- }
- if (saveableURL == null) {
- saveableURL = new StringBuffer(url);
- } else {
- // since HTTP is the same regardless of whether it runs on TCP or on SSL/TCP
- if (protocol.equals("HTTP/1.1") && request.isSecure() && saveableURL.toString().startsWith("http://")) {
- saveableURL.replace(0, 4, "https"); // todo: this needs to be tested extensively.
- }
+ saveableURL = getRequestURL(request);
}
+ // fix the protocol
+ fixProtocol(saveableURL, request);
// add the query string, if any
String queryString = request.getQueryString();
if (queryString != null) {
return saveableURL.toString();
}
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // The following methods are provided for compatibility with various app servers. //
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
/**
- * Parse the username out of the BASIC authorization header string.
- * @param authorization
- * @return
+ * Set the filter configuration, included for WebLogic 6 compatibility.
+ *
+ * @param config filter configuration object
*/
- private String parseUsername(String authorization) {
- String unencoded = decodeBasicAuthorizationString(authorization);
- if (unencoded == null) {
- return null;
- } else {
- int colon = unencoded.indexOf(':');
- if (colon < 0) {
- return null;
- } else {
- return unencoded.substring(0, colon).trim();
- }
- }
+ public void setFilterConfig(FilterConfig config) throws ServletException {
+ init(config);
}
/**
- * Parse the password out of the BASIC authorization header string.
- * @param authorization
- * @return
+ * Get the filter config object, included for WebLogic 6 compatibility.
*/
- private String parsePassword(String authorization) {
- String unencoded = decodeBasicAuthorizationString(authorization);
- if (unencoded == null) {
- return null;
- } else {
- int colon = unencoded.indexOf(':');
- if (colon < 0) {
- return (null);
+ public FilterConfig getFilterConfig() {
+ return config;
+ }
+
+ /**
+ * Get the requestURL.
+ * This method is called when the app server fails to implement HttpServletRequest.getRequestURL().
+ * Orion 1.5.2 is one such server.
+ */
+ private static StringBuffer getRequestURL(HttpServletRequest request) {
+ String protocol = request.getProtocol();
+ int port = request.getServerPort();
+ String portString = ":" + port;
+
+ // todo: this needs to be tested to see if it still an issue; remove it if it is not needed
+ // Set the portString to the empty string if the requrest came in on the default port.
+ // This will keep Netscape from dropping the session, which happens when the port is added where it wasn't before.
+ // This is not perfect, but most requests on the default ports will not be made with an explicit port number.
+ if (protocol.equals("HTTP/1.1")) {
+ if (!request.isSecure()) {
+ if (port == 80) {
+ portString = "";
+ }
} else {
- return unencoded.substring(colon + 1).trim();
+ if (port == 443) {
+ portString = "";
+ }
}
}
+
+ // construct the saveable URL string
+ return new StringBuffer(protocol + request.getServerName() + portString + request.getRequestURI());
}
/**
- * Decode the BASIC authorization string.
+ * Fix the protocol portion of an absolute url. Often, the protocol will be http: even for https: requests.
+ *
+ * todo: needs testing to make sure this is proper in all circumstances
*
- * @param authorization
- * @return
+ * @param url
+ * @param request
*/
- private String decodeBasicAuthorizationString(String authorization) {
- if (authorization == null || !authorization.toLowerCase().startsWith("basic ")) {
- return null;
- } else {
- authorization = authorization.substring(6).trim();
- // Decode and parse the authorization credentials
- return new String(base64Helper.decodeBase64(authorization.getBytes()));
+ private static void fixProtocol(StringBuffer url, HttpServletRequest request) {
+ // fix protocol, if needed (since HTTP is the same regardless of whether it runs on TCP or on SSL/TCP)
+ if (
+ request.getProtocol().equals("HTTP/1.1")
+ && request.isSecure()
+ && url.toString().startsWith("http://")
+ ) {
+ url.replace(0, 4, "https");
}
}
}
/*
- * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/filter/SecurityRequestWrapper.java,v 1.8 2003/07/07 04:16:40 maxcooper Exp $
- * $Revision: 1.8 $
- * $Date: 2003/07/07 04:16:40 $
+ * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/filter/SecurityRequestWrapper.java,v 1.9 2003/07/07 13:12:57 maxcooper Exp $
+ * $Revision: 1.9 $
+ * $Date: 2003/07/07 13:12:57 $
*
* ====================================================================
* The SecurityFilter Software License, Version 1.1
import org.securityfilter.realm.SecurityRealmInterface;
-import javax.servlet.ServletInputStream;
-import javax.servlet.ServletRequest;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.*;
+import javax.servlet.http.*;
import java.io.IOException;
import java.security.Principal;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
/**
* SecurityRequestWrapper
* @author Max Cooper (max@maxcooper.com)
* @author Daya Sharma (iamdaya@yahoo.com, billydaya@sbcglobal.net)
* @author Torgeir Veimo (torgeir@pobox.com)
- * @version $Revision: 1.8 $ $Date: 2003/07/07 04:16:40 $
+ * @version $Revision: 1.9 $ $Date: 2003/07/07 13:12:57 $
*/
public class SecurityRequestWrapper extends HttpServletRequestWrapper {
public static final String PRINCIPAL_SESSION_KEY = SecurityRequestWrapper.class.getName() + ".PRINCIPAL";
private HttpServletRequest currentRequest;
private SecurityRealmInterface realm;
private SavedRequest savedRequest;
+ private String authType;
+ private String matchableURL;
/**
* Construct a new SecurityRequestWrapper.
* @param savedRequest SavedRequest (usually null, unless this is the request
* that invoked the authorization sequence)
*/
- public SecurityRequestWrapper(HttpServletRequest request, SecurityRealmInterface realm, SavedRequest savedRequest) {
+ public SecurityRequestWrapper(
+ HttpServletRequest request,
+ SavedRequest savedRequest,
+ SecurityRealmInterface realm,
+ String authType
+ ) {
super(request);
this.currentRequest = request;
this.realm = realm;
this.savedRequest = savedRequest;
+ this.authType = authType;
+ initMatchableURL();
}
/**
}
/**
- * Returns FORM_AUTH if the user has been authenticated, null otherwise.
- *
- * todo: add BASIC support
+ * Returns the auth type (e.g. FORM, BASIC, etc.).
*/
public String getAuthType() {
if (getUserPrincipal() != null) {
- return HttpServletRequest.FORM_AUTH;
+ return authType;
} else {
return null;
}
return super.getMethod();
}
}
+
+ /**
+ * Get a URL that can be matched against security URL patterns.
+ *
+ * This is the part after the contextPath, with the pathInfo, but without the query string.
+ * http://server:8080/contextPath/someURL.jsp?param=value becomes /someURL.jsp
+ */
+ public String getMatchableURL() {
+ return matchableURL;
+ }
+
+ /**
+ * Initilize the matchableURL.
+ */
+ private void initMatchableURL() {
+ // extract the servlet path portion that needs to be checked
+ matchableURL = currentRequest.getServletPath();
+ // add the pathInfo, as it needs to be part of the URL we check
+ String pathInfo = currentRequest.getPathInfo();
+ if (pathInfo != null) {
+ matchableURL = matchableURL + pathInfo;
+ }
+ }
}
// ------------------------------------------------------------------------