From 6c26e79a0f7e9331c7311e90333656b9057976ba Mon Sep 17 00:00:00 2001
From: Colin Sampaleanu
* Returns a {@link PrincipalAcegiUserToken} to JBoss' authentication system,
* which is subsequently available from
@@ -55,11 +56,15 @@ import javax.security.auth.login.LoginException;
* @version $Id$
*/
public class JbossAcegiLoginModule extends AbstractServerLoginModule {
+ //~ Instance fields ========================================================
+
private AuthenticationManager authenticationManager;
private Principal identity;
private String key;
private char[] credential;
+ //~ Methods ================================================================
+
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options) {
super.initialize(subject, callbackHandler, sharedState, options);
@@ -78,8 +83,8 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
}
if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) {
- throw new IllegalArgumentException("Cannot locate " +
- appContextLocation);
+ throw new IllegalArgumentException("Cannot locate "
+ + appContextLocation);
}
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(appContextLocation);
@@ -104,8 +109,8 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
if ((username == null) && (password == null)) {
identity = null;
- super.log.trace("Authenticating as unauthenticatedIdentity=" +
- identity);
+ super.log.trace("Authenticating as unauthenticatedIdentity="
+ + identity);
}
if (username == null) {
@@ -145,8 +150,8 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
}
super.loginOk = true;
- super.log.trace("User '" + identity + "' authenticated, loginOk=" +
- loginOk);
+ super.log.trace("User '" + identity + "' authenticated, loginOk="
+ + loginOk);
return true;
}
@@ -157,7 +162,7 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
protected Group[] getRoleSets() throws LoginException {
SimpleGroup roles = new SimpleGroup("Roles");
- Group[] roleSets = { roles };
+ Group[] roleSets = {roles};
if (this.identity instanceof Authentication) {
Authentication user = (Authentication) this.identity;
@@ -172,17 +177,17 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
}
protected String[] getUsernameAndPassword() throws LoginException {
- String[] info = { null, null };
+ String[] info = {null, null};
// prompt for a username and password
if (callbackHandler == null) {
- throw new LoginException("Error: no CallbackHandler available " +
- "to collect authentication information");
+ throw new LoginException("Error: no CallbackHandler available "
+ + "to collect authentication information");
}
NameCallback nc = new NameCallback("User name: ", "guest");
PasswordCallback pc = new PasswordCallback("Password: ", false);
- Callback[] callbacks = { nc, pc };
+ Callback[] callbacks = {nc, pc};
String username = null;
String password = null;
@@ -202,8 +207,8 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
} catch (java.io.IOException ioe) {
throw new LoginException(ioe.toString());
} catch (UnsupportedCallbackException uce) {
- throw new LoginException("CallbackHandler does not support: " +
- uce.getCallback());
+ throw new LoginException("CallbackHandler does not support: "
+ + uce.getCallback());
}
info[0] = username;
diff --git a/changelog.txt b/changelog.txt
index 98d1560cc9..369f4875e2 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,10 @@
+Changes in version 0.5 (2004-xx-xx)
+-----------------------------------
+* AuthenticationProcessingFilter by default finds configuration context using Spring's WebApplicationContextUtils.getWebApplicationContext()
+* AuthenticationProcessingFilter context may optionally be specified with 'contextConfigLocation' param (was previously 'appContextLocation')
+* SecurityEnforcementFilter by default finds configuration context using Spring's WebApplicationContextUtils.getWebApplicationContext()
+* SecurityEnforcementFilter context may optionally be specified with 'contextConfigLocation' param (was previously 'appContextLocation')
+
Changes in version 0.4 (2004-04-03)
-----------------------------------
diff --git a/core/src/main/java/org/acegisecurity/AcegiSecurityException.java b/core/src/main/java/org/acegisecurity/AcegiSecurityException.java
index c17d5b691a..af7f7d43f6 100644
--- a/core/src/main/java/org/acegisecurity/AcegiSecurityException.java
+++ b/core/src/main/java/org/acegisecurity/AcegiSecurityException.java
@@ -21,7 +21,7 @@ import org.springframework.core.NestedRuntimeException;
/**
* Abstract superclass for all exceptions thrown in the security package and
* subpackages.
- *
+ *
*
* Note that this is a runtime (unchecked) exception. Security exceptions are
* usually fatal; there is no reason for them to be checked.
diff --git a/core/src/main/java/org/acegisecurity/intercept/web/SecurityEnforcementFilter.java b/core/src/main/java/org/acegisecurity/intercept/web/SecurityEnforcementFilter.java
index c6d7b24dfc..86c6307cdb 100644
--- a/core/src/main/java/org/acegisecurity/intercept/web/SecurityEnforcementFilter.java
+++ b/core/src/main/java/org/acegisecurity/intercept/web/SecurityEnforcementFilter.java
@@ -22,8 +22,12 @@ import net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
import java.io.IOException;
import java.util.Map;
@@ -41,12 +45,12 @@ import javax.servlet.http.HttpServletResponse;
/**
* Wraps requests to the {@link FilterSecurityInterceptor}.
*
- *
- * This filter is necessary because it provides an application context
- * environment for the
+ * This filter is necessary because it provides the bridge between incoming
+ * requests and the
+ *
* If a {@link AuthenticationException} is detected, the filter will redirect
* to the
+ *
+ * This filter works with a
* To use this filter, it is necessary to specify the following filter
* initialization parameters:
+ * FilterSecurityInterceptor instance.
+ * FilterSecurityInterceptor instance.
* loginFormUrl. This allows common handling of
* authentication failures originating from any subclass of {@link
@@ -60,33 +64,55 @@ import javax.servlet.http.HttpServletResponse;
* security interceptor.
* FilterSecurityInterceptor instance. By
+ * default, at init time, the filter will use Spring's {@link
+ * WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)}
+ * method to obtain an ApplicationContext instance, inside which must be a
+ * configured FilterSecurityInterceptor instance. In the case
+ * where it is desireable for this filter to instantiate its own
+ * ApplicationContext instance from which to obtain the
+ * FilterSecurityInterceptor, the location of the config for this
+ * context may be specified with the optional
+ * contextConfigLocation init param.
+ *
*
- * appContextLocation indicates the path to an application context
- * that contains the FilterSecurityInterceptor.
- * loginFormUrl indicates the URL that should be used for
* redirection if an AuthenticationException is detected.
* contextConfigLocation (optional, normally not used), indicates
+ * the path to an application context that contains a properly configured
+ * FilterSecurityInterceptor. If not specified, {@link
+ * WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)}
+ * will be used to obtain the context.
+ *
AuthenticationException is detected.
*/
protected String loginFormUrl;
+ private ApplicationContext ctx;
+ private boolean ourContext = false;
//~ Methods ================================================================
public void destroy() {
- ctx.close();
+ if (ourContext && ctx instanceof ConfigurableApplicationContext) {
+ ((ConfigurableApplicationContext) ctx).close();
+ }
}
public void doFilter(ServletRequest request, ServletResponse response,
@@ -145,15 +175,15 @@ public class SecurityEnforcementFilter implements Filter {
}
public void init(FilterConfig filterConfig) throws ServletException {
- String appContextLocation = filterConfig.getInitParameter(
- "appContextLocation");
+ String appContextLocation = filterConfig.getInitParameter(CONFIG_LOCATION_PARAM);
- if ((appContextLocation == null) || "".equals(appContextLocation)) {
- throw new ServletException("appContextLocation must be specified");
- }
+ if ((appContextLocation != null) && (appContextLocation.length() > 0)) {
+ ourContext = true;
- if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) {
- throw new ServletException("Cannot locate " + appContextLocation);
+ if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) {
+ throw new ServletException("Cannot locate "
+ + appContextLocation);
+ }
}
loginFormUrl = filterConfig.getInitParameter("loginFormUrl");
@@ -162,7 +192,21 @@ public class SecurityEnforcementFilter implements Filter {
throw new ServletException("loginFormUrl must be specified");
}
- ctx = new ClassPathXmlApplicationContext(appContextLocation);
+ try {
+ if (!ourContext) {
+ ctx = WebApplicationContextUtils
+ .getRequiredWebApplicationContext(filterConfig
+ .getServletContext());
+ } else {
+ ctx = new ClassPathXmlApplicationContext(appContextLocation);
+ }
+ } catch (RuntimeException e) {
+ throw new ServletException(
+ "Error obtaining/creating ApplicationContext for config. Must be stored in ServletContext, or optionally '"
+ + CONFIG_LOCATION_PARAM
+ + "' param may be used to allow creation of new context by this filter. See root error for additional details",
+ e);
+ }
Map beans = ctx.getBeansOfType(FilterSecurityInterceptor.class, true,
true);
diff --git a/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilter.java b/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilter.java
index c9d4185e59..ba08b40d3e 100644
--- a/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilter.java
+++ b/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilter.java
@@ -23,8 +23,12 @@ import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
import java.io.IOException;
import java.util.Map;
@@ -52,30 +56,39 @@ import javax.servlet.http.HttpServletResponse;
* HttpSessionIntegrationFilter#ACEGI_SECURITY_AUTHENTICATION_KEY}.
*
*
- * + *
* Login forms must present two parameters to this filter: a username and * password. The filter will process the login against the authentication * environment that was configured from a Spring application context defined * in the filter initialization. *
* - *+ *
* If authentication fails, the AuthenticationException will be
* placed into the HttpSession with the attribute defined by
* {@link #ACEGI_SECURITY_LAST_EXCEPTION_KEY}.
*
+ *
+ * This filter works with an {@link AuthenticationManager} which is used to
+ * process each authentication request. By default, at init time, the filter
+ * will use Spring's {@link
+ * WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)}
+ * method to obtain an ApplicationContext instance, inside which must be a
+ * configured AuthenticationManager instance. In the case where it is
+ * desireable for this filter to instantiate its own ApplicationContext
+ * instance from which to obtain the AuthenticationManager, the location of
+ * the config for this context may be specified with the optional
+ * appContextLocation init param.
+ *
* To use this filter, it is necessary to specify the following filter * initialization parameters: + *
* *appContextLocation indicates the path to an application context
- * that contains an {@link AuthenticationManager} that should be used to
- * process each authentication request.
- * defaultTargetUrl indicates the URL that should be used for
* redirection if the HttpSession attribute named {@link
* #ACEGI_SECURITY_TARGET_URL_KEY} does not indicate the target URL once
@@ -91,15 +104,29 @@ import javax.servlet.http.HttpServletResponse;
* respond to. This parameter is optional, and defaults to
* /j_acegi_security_check.
* appContextLocation (optional, normally not used), indicates the
+ * path to an application context that contains an {@link
+ * AuthenticationManager} which should be used to process each authentication
+ * request. If not specified, {@link
+ * WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)}
+ * will be used to obtain the context.
+ * /j_acegi_security_check)
*/
private String filterProcessesUrl;
+ private boolean ourContext = false;
//~ Methods ================================================================
public void destroy() {
- ctx.close();
+ if (ourContext && ctx instanceof ConfigurableApplicationContext) {
+ ((ConfigurableApplicationContext) ctx).close();
+ }
}
public void doFilter(ServletRequest request, ServletResponse response,
@@ -216,15 +246,15 @@ public class AuthenticationProcessingFilter implements Filter {
}
public void init(FilterConfig filterConfig) throws ServletException {
- String appContextLocation = filterConfig.getInitParameter(
- "appContextLocation");
+ String appContextLocation = filterConfig.getInitParameter(CONFIG_LOCATION_PARAM);
- if ((appContextLocation == null) || "".equals(appContextLocation)) {
- throw new ServletException("appContextLocation must be specified");
- }
+ if ((appContextLocation != null) && (appContextLocation.length() > 0)) {
+ ourContext = true;
- if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) {
- throw new ServletException("Cannot locate " + appContextLocation);
+ if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) {
+ throw new ServletException("Cannot locate "
+ + appContextLocation);
+ }
}
defaultTargetUrl = filterConfig.getInitParameter("defaultTargetUrl");
@@ -248,7 +278,21 @@ public class AuthenticationProcessingFilter implements Filter {
filterProcessesUrl = "/j_acegi_security_check";
}
- ctx = new ClassPathXmlApplicationContext(appContextLocation);
+ try {
+ if (!ourContext) {
+ ctx = WebApplicationContextUtils
+ .getRequiredWebApplicationContext(filterConfig
+ .getServletContext());
+ } else {
+ ctx = new ClassPathXmlApplicationContext(appContextLocation);
+ }
+ } catch (RuntimeException e) {
+ throw new ServletException(
+ "Error obtaining/creating ApplicationContext for config. Must be stored in ServletContext, or optionally '"
+ + CONFIG_LOCATION_PARAM
+ + "' param may be used to allow creation of new context by this filter. See root error for additional details",
+ e);
+ }
Map beans = ctx.getBeansOfType(AuthenticationManager.class, true, true);
diff --git a/core/src/test/java/org/acegisecurity/intercept/web/SecurityEnforcementFilterTests.java b/core/src/test/java/org/acegisecurity/intercept/web/SecurityEnforcementFilterTests.java
index a32dcd3700..1aacc9364a 100644
--- a/core/src/test/java/org/acegisecurity/intercept/web/SecurityEnforcementFilterTests.java
+++ b/core/src/test/java/org/acegisecurity/intercept/web/SecurityEnforcementFilterTests.java
@@ -150,8 +150,7 @@ public class SecurityEnforcementFilterTests extends TestCase {
}
}
- public void testStartupDetectsMissingAppContextLocation()
- throws Exception {
+ public void testStartupDetectsMissingAppContext() throws Exception {
MockFilterConfig config = new MockFilterConfig();
config.setInitParmeter("loginFormUrl", "/login.jsp");
@@ -161,8 +160,7 @@ public class SecurityEnforcementFilterTests extends TestCase {
filter.init(config);
fail("Should have thrown ServletException");
} catch (ServletException expected) {
- assertEquals("appContextLocation must be specified",
- expected.getMessage());
+ assertTrue(expected.getMessage().startsWith("Error obtaining/creating ApplicationContext for config."));
}
config.setInitParmeter("appContextLocation", "");
@@ -171,8 +169,7 @@ public class SecurityEnforcementFilterTests extends TestCase {
filter.init(config);
fail("Should have thrown ServletException");
} catch (ServletException expected) {
- assertEquals("appContextLocation must be specified",
- expected.getMessage());
+ assertTrue(expected.getMessage().startsWith("Error obtaining/creating ApplicationContext for config."));
}
}
diff --git a/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterTests.java b/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterTests.java
index 9b024cce48..0992b664cc 100644
--- a/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterTests.java
+++ b/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterTests.java
@@ -287,8 +287,7 @@ public class AuthenticationProcessingFilterTests extends TestCase {
}
}
- public void testStartupDetectsMissingAppContextLocation()
- throws Exception {
+ public void testStartupDetectsMissingAppContext() throws Exception {
MockFilterConfig config = new MockFilterConfig();
config.setInitParmeter("defaultTargetUrl", "/");
config.setInitParmeter("authenticationFailureUrl", "/failed.jsp");
@@ -299,8 +298,7 @@ public class AuthenticationProcessingFilterTests extends TestCase {
filter.init(config);
fail("Should have thrown ServletException");
} catch (ServletException expected) {
- assertEquals("appContextLocation must be specified",
- expected.getMessage());
+ assertTrue(expected.getMessage().startsWith("Error obtaining/creating ApplicationContext for config."));
}
config.setInitParmeter("appContextLocation", "");
@@ -309,8 +307,7 @@ public class AuthenticationProcessingFilterTests extends TestCase {
filter.init(config);
fail("Should have thrown ServletException");
} catch (ServletException expected) {
- assertEquals("appContextLocation must be specified",
- expected.getMessage());
+ assertTrue(expected.getMessage().startsWith("Error obtaining/creating ApplicationContext for config."));
}
}
diff --git a/test/.cvsignore b/test/.cvsignore
new file mode 100644
index 0000000000..91696b3e12
--- /dev/null
+++ b/test/.cvsignore
@@ -0,0 +1,2 @@
+acegisecuritytest.properties
+acegisecuritytest.script
diff --git a/upgrade-04-05.txt b/upgrade-04-05.txt
new file mode 100644
index 0000000000..2a8c240054
--- /dev/null
+++ b/upgrade-04-05.txt
@@ -0,0 +1,23 @@
+===============================================================================
+ ACEGI SECURITY SYSTEM FOR SPRING - UPGRADING FROM 0.4 TO 0.5
+===============================================================================
+
+Unfortunately, changes to the API and package locations were required. The
+following should help most casual users of the project update their
+applications:
+
+- By default, AuthenticationProcessingFilter and SecurityEnforcementFilter now
+ use Spring's WebApplicationContextUtils.getApplicationContext to load the
+ ApplicationContext in which their respective configs may be found. Ideally,
+ move your configuration for these filters from the separate contexts you were
+ using before, to the main context used by your webapp. Alternately, the old
+ mechanism of having the filter load its own specific context is still
+ supported, but the param specifying the location of this context has been
+ changed to match the equivalent param as used by Spring's ContextLoader class.
+ If you do still want to use this approach, just rename your param from
+ 'appContextLocation' to 'contextConfigLocation'.
+
+
+We hope you find the new features useful in your projects.
+
+$Id$