Significantly refactor "well-known location model" to authentication processing mechanism and HttpSessionContextIntegrationFilter model.

This commit is contained in:
Ben Alex 2005-02-21 06:48:31 +00:00
parent ba02d45677
commit dda66a0454
63 changed files with 1332 additions and 1345 deletions

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,7 +16,14 @@
package net.sf.acegisecurity.adapters.jboss; package net.sf.acegisecurity.adapters.jboss;
import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.ui.AbstractIntegrationFilter; import net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter;
import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.context.security.SecureContextUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.IOException;
import java.security.Principal; import java.security.Principal;
@ -28,33 +35,88 @@ import javax.naming.NamingException;
import javax.security.auth.Subject; import javax.security.auth.Subject;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/** /**
* Populates a {@link net.sf.acegisecurity.context.SecureContext} from JBoss' * Populates a {@link net.sf.acegisecurity.context.security.SecureContext} from
* <code>java:comp/env/security/subject</code>. * JBoss' <code>java:comp/env/security/subject</code>.
* *
* <p> * <p>
* See {@link AbstractIntegrationFilter} for further information. * This filter <b>never</b> preserves the <code>Authentication</code> on the
* <code>ContextHolder</code> - it is replaced every request.
* </p>
*
* <p>
* See {@link HttpSessionContextIntegrationFilter} for further information.
* </p> * </p>
* *
* @author Ben Alex * @author Ben Alex
* @version $Id$ * @version $Id$
*/ */
public class JbossIntegrationFilter extends AbstractIntegrationFilter { public class JbossIntegrationFilter implements Filter {
//~ Static fields/initializers =============================================
private static final Log logger = LogFactory.getLog(JbossIntegrationFilter.class);
//~ Methods ================================================================ //~ Methods ================================================================
/** /**
* Not supported for this type of well-known location. * Does nothing. We use IoC container lifecycle services instead.
*
* @param request DOCUMENT ME!
* @param authentication DOCUMENT ME!
*/ */
public void commitToContainer(ServletRequest request, public void destroy() {}
Authentication authentication) {}
public Object extractFromContainer(ServletRequest request) { public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
SecureContext sc = SecureContextUtils.getSecureContext();
Object principal = extractFromContainer(request);
if ((principal != null) && principal instanceof Authentication) {
sc.setAuthentication((Authentication) principal);
if (logger.isDebugEnabled()) {
logger.debug(
"ContextHolder updated with Authentication from container: '"
+ principal + "'");
}
} else {
if (logger.isDebugEnabled()) {
logger.debug(
"ContextHolder not set with new Authentication as Principal was: '"
+ principal + "'");
}
}
chain.doFilter(request, response);
}
/**
* Does nothing. We use IoC container lifecycle services instead.
*
* @param arg0 ignored
*
* @throws ServletException ignored
*/
public void init(FilterConfig arg0) throws ServletException {}
/**
* Provided so that unit tests can override.
*
* @return a <code>Context</code> that can be used for lookup
*
* @throws NamingException DOCUMENT ME!
*/
protected Context getLookupContext() throws NamingException {
return new InitialContext();
}
private Object extractFromContainer(ServletRequest request) {
Subject subject = null; Subject subject = null;
try { try {
@ -94,15 +156,4 @@ public class JbossIntegrationFilter extends AbstractIntegrationFilter {
return null; return null;
} }
/**
* Provided so that unit tests can override.
*
* @return a <code>Context</code> that can be used for lookup
*
* @throws NamingException DOCUMENT ME!
*/
protected Context getLookupContext() throws NamingException {
return new InitialContext();
}
} }

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,9 +20,14 @@ import junit.framework.TestCase;
import net.sf.acegisecurity.GrantedAuthority; import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl; import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.adapters.PrincipalAcegiUserToken; import net.sf.acegisecurity.adapters.PrincipalAcegiUserToken;
import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.context.security.SecureContextUtils;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
import java.io.IOException;
import java.security.Principal; import java.security.Principal;
import java.util.HashSet; import java.util.HashSet;
@ -32,6 +37,13 @@ import javax.naming.Context;
import javax.security.auth.Subject; import javax.security.auth.Subject;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/** /**
* Tests {@link JbossIntegrationFilter}. * Tests {@link JbossIntegrationFilter}.
@ -52,15 +64,11 @@ public class JbossIntegrationFilterTests extends TestCase {
//~ Methods ================================================================ //~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
public static void main(String[] args) { public static void main(String[] args) {
junit.textui.TestRunner.run(JbossIntegrationFilterTests.class); junit.textui.TestRunner.run(JbossIntegrationFilterTests.class);
} }
public void testCorrectOperation() { public void testCorrectOperation() throws Exception {
PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key", PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key",
"someone", "password", "someone", "password",
new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")}); new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")});
@ -68,59 +76,77 @@ public class JbossIntegrationFilterTests extends TestCase {
JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext( JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(
makeIntoSubject(principal))); makeIntoSubject(principal)));
Object result = filter.extractFromContainer(new MockHttpServletRequest()); MockHttpServletRequest request = new MockHttpServletRequest();
MockFilterChain chain = new MockFilterChain();
if (!(result instanceof PrincipalAcegiUserToken)) { filter.doFilter(request, null, chain);
fail("Should have returned PrincipalAcegiUserToken");
}
PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result; assertEquals(principal,
assertEquals(principal, result); SecureContextUtils.getSecureContext().getAuthentication());
ContextHolder.setContext(null);
MockHttpServletRequest mockRequest = new MockHttpServletRequest();
mockRequest.setUserPrincipal(principal);
filter.commitToContainer(mockRequest, principal);
} }
public void testReturnsNullIfContextReturnsSomethingOtherThanASubject() { public void testReturnsNullIfContextReturnsSomethingOtherThanASubject()
throws Exception {
JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext( JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(
"THIS_IS_NOT_A_SUBJECT")); "THIS_IS_NOT_A_SUBJECT"));
assertEquals(null,
filter.extractFromContainer(new MockHttpServletRequest(null, null))); MockHttpServletRequest request = new MockHttpServletRequest();
MockFilterChain chain = new MockFilterChain();
filter.doFilter(request, null, chain);
assertNull(SecureContextUtils.getSecureContext().getAuthentication());
} }
public void testReturnsNullIfInitialContextHasNullPrincipal() { public void testReturnsNullIfInitialContextHasNullPrincipal()
throws Exception {
JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext( JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(
makeIntoSubject(null))); makeIntoSubject(null)));
assertEquals(null,
filter.extractFromContainer(new MockHttpServletRequest(null, null))); MockHttpServletRequest request = new MockHttpServletRequest();
MockFilterChain chain = new MockFilterChain();
filter.doFilter(request, null, chain);
assertNull(SecureContextUtils.getSecureContext().getAuthentication());
} }
public void testReturnsNullIfInitialContextHasNullSubject() { public void testReturnsNullIfInitialContextHasNullSubject()
throws Exception {
JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext( JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(
null)); null));
assertEquals(null,
filter.extractFromContainer(new MockHttpServletRequest(null, null))); MockHttpServletRequest request = new MockHttpServletRequest();
MockFilterChain chain = new MockFilterChain();
filter.doFilter(request, null, chain);
assertNull(SecureContextUtils.getSecureContext().getAuthentication());
} }
public void testReturnsNullIfInitialContextIsNull() { public void testReturnsNullIfInitialContextIsNull()
throws Exception {
JbossIntegrationFilter filter = new MockJbossIntegrationFilter(null); JbossIntegrationFilter filter = new MockJbossIntegrationFilter(null);
Object result = filter.extractFromContainer(new MockHttpServletRequest( MockHttpServletRequest request = new MockHttpServletRequest();
null, null)); MockFilterChain chain = new MockFilterChain();
assertEquals(null, filter.extractFromContainer(null));
filter.doFilter(request, null, chain);
assertNull(SecureContextUtils.getSecureContext().getAuthentication());
} }
public void testReturnsNullIfPrincipalNotAnAuthenticationImplementation() { public void testReturnsNullIfPrincipalNotAnAuthenticationImplementation()
throws Exception {
JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext( JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(
makeIntoSubject(new Principal() { makeIntoSubject(new Principal() {
public String getName() { public String getName() {
return "MockPrincipal"; return "MockPrincipal";
} }
}))); })));
assertEquals(null,
filter.extractFromContainer(new MockHttpServletRequest(null, null))); MockHttpServletRequest request = new MockHttpServletRequest();
MockFilterChain chain = new MockFilterChain();
filter.doFilter(request, null, chain);
assertNull(SecureContextUtils.getSecureContext().getAuthentication());
} }
public void testTestingObjectReturnsInitialContext() public void testTestingObjectReturnsInitialContext()
@ -129,10 +155,35 @@ public class JbossIntegrationFilterTests extends TestCase {
assertTrue(filter.getLookupContext() instanceof Context); assertTrue(filter.getLookupContext() instanceof Context);
} }
protected void setUp() throws Exception {
super.setUp();
ContextHolder.setContext(new SecureContextImpl());
}
protected void tearDown() throws Exception {
super.tearDown();
ContextHolder.setContext(null);
}
private void executeFilterInContainerSimulator(FilterConfig filterConfig,
Filter filter, ServletRequest request, ServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
filter.init(filterConfig);
filter.doFilter(request, response, filterChain);
filter.destroy();
}
private Subject makeIntoSubject(Principal principal) { private Subject makeIntoSubject(Principal principal) {
Set principals = new HashSet(); Set principals = new HashSet();
principals.add(principal); principals.add(principal);
return new Subject(false, principals, new HashSet(), new HashSet()); return new Subject(false, principals, new HashSet(), new HashSet());
} }
//~ Inner Classes ==========================================================
private class MockFilterChain implements FilterChain {
public void doFilter(ServletRequest arg0, ServletResponse arg1)
throws IOException, ServletException {}
}
} }

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -29,7 +29,8 @@ import java.security.Principal;
* </p> * </p>
* *
* <p> * <p>
* Stored in a request {@link net.sf.acegisecurity.context.SecureContext}. * Stored in a request {@link
* net.sf.acegisecurity.context.security.SecureContext}.
* </p> * </p>
* *
* @author Ben Alex * @author Ben Alex

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,7 +18,7 @@ package net.sf.acegisecurity;
/** /**
* Thrown if an authentication request is rejected because there is no {@link * Thrown if an authentication request is rejected because there is no {@link
* Authentication} object in the {@link * Authentication} object in the {@link
* net.sf.acegisecurity.context.SecureContext}. * net.sf.acegisecurity.context.security.SecureContext}.
* *
* @author Ben Alex * @author Ben Alex
* @version $Id$ * @version $Id$

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -25,8 +25,8 @@ package net.sf.acegisecurity;
* object invocation only. The {@link * object invocation only. The {@link
* net.sf.acegisecurity.intercept.AbstractSecurityInterceptor} will replace * net.sf.acegisecurity.intercept.AbstractSecurityInterceptor} will replace
* the <code>Authentication</code> object held in the {@link * the <code>Authentication</code> object held in the {@link
* net.sf.acegisecurity.context.SecureContext} for the duration of the secure * net.sf.acegisecurity.context.security.SecureContext} for the duration of
* object callback only, returning it to the original * the secure object callback only, returning it to the original
* <code>Authentication</code> object when the callback ends. * <code>Authentication</code> object when the callback ends.
* </p> * </p>
* *

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,27 +16,47 @@
package net.sf.acegisecurity.adapters; package net.sf.acegisecurity.adapters;
import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.ui.AbstractIntegrationFilter; import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.context.security.SecureContextUtils;
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 java.io.IOException;
import java.security.Principal;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
/** /**
* Populates a {@link net.sf.acegisecurity.context.SecureContext} from the * Populates <code>ContextHolder</code> with the <code>Authentication</code>
* container's <code>HttpServletRequest.getUserPrincipal()</code>. * obtained from the container's
* <code>HttpServletRequest.getUserPrincipal()</code>.
* *
* <p> * <p>
* See {@link AbstractIntegrationFilter} for further information. * Used this filter with container adapters only.
* </p>
*
* <p>
* This filter <b>never</b> preserves the <code>Authentication</code> on the
* <code>ContextHolder</code> - it is replaced every request.
* </p>
*
* <p>
* See {@link HttpSessionContextIntegrationFilter} for further information.
* </p> * </p>
* *
* @author Ben Alex * @author Ben Alex
* @version $Id$ * @version $Id$
*/ */
public class HttpRequestIntegrationFilter extends AbstractIntegrationFilter { public class HttpRequestIntegrationFilter implements Filter {
//~ Static fields/initializers ============================================= //~ Static fields/initializers =============================================
private static final Log logger = LogFactory.getLog(HttpRequestIntegrationFilter.class); private static final Log logger = LogFactory.getLog(HttpRequestIntegrationFilter.class);
@ -44,19 +64,47 @@ public class HttpRequestIntegrationFilter extends AbstractIntegrationFilter {
//~ Methods ================================================================ //~ Methods ================================================================
/** /**
* Not supported for this type of well-known location. * Does nothing. We use IoC container lifecycle services instead.
*
* @param request DOCUMENT ME!
* @param authentication DOCUMENT ME!
*/ */
public void commitToContainer(ServletRequest request, public void destroy() {}
Authentication authentication) {}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
SecureContext sc = SecureContextUtils.getSecureContext();
public Object extractFromContainer(ServletRequest request) {
if (request instanceof HttpServletRequest) { if (request instanceof HttpServletRequest) {
return ((HttpServletRequest) request).getUserPrincipal(); Principal principal = ((HttpServletRequest) request)
.getUserPrincipal();
if ((principal != null) && principal instanceof Authentication) {
sc.setAuthentication((Authentication) principal);
if (logger.isDebugEnabled()) {
logger.debug(
"ContextHolder updated with Authentication from container: '"
+ principal + "'");
}
} else {
if (logger.isDebugEnabled()) {
logger.debug(
"ContextHolder not set with new Authentication as Principal was: '"
+ principal + "'");
}
}
} else { } else {
return null; throw new IllegalArgumentException(
"Only HttpServletRequest is acceptable");
} }
chain.doFilter(request, response);
} }
/**
* Does nothing. We use IoC container lifecycle services instead.
*
* @param arg0 ignored
*
* @throws ServletException ignored
*/
public void init(FilterConfig arg0) throws ServletException {}
} }

View File

@ -0,0 +1,289 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.acegisecurity.context;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
/**
* <p>
* Populates the <code>ContextHolder</code> with information obtained from the
* <code>HttpSession</code>.
* </p>
*
* <p>
* The <code>HttpSession</code> will be queried to retrieve the
* <code>Context</code> that should be stored against the
* <code>ContextHolder</code> for the duration of the web request. At the end
* of the web request, any updates made to the <code>ContextHolder</code> will
* be persisted back to the <code>HttpSession</code> by this filter.
* </p>
*
* <p>
* If a valid <code>Context</code> cannot be obtained from the
* <code>HttpSession</code> for whatever reason, a fresh <code>Context</code>
* will be created and used instead. The created object will be of the
* instance defined by the {@link #setContext(Class)} method.
* </p>
*
* <p>
* No <code>HttpSession</code> will be created by this filter if one does not
* already exist. If at the end of the web request the
* <code>HttpSession</code> does not exist, a <code>HttpSession</code> will
* <b>only</b> be created if the current contents of
* <code>ContextHolder</code> are not {@link
* java.lang.Object#equals(java.lang.Object)} to a <code>new</code> instance
* of {@link #setContext(Class)}. This avoids needless
* <code>HttpSession</code> creation, but automates the storage of changes
* made to the <code>ContextHolder</code>.
* </p>
*
* <P>
* This filter will only execute once per request, to resolve servlet container
* (specifically Weblogic) incompatibilities.
* </p>
*
* <p>
* If for whatever reason no <code>HttpSession</code> should <b>ever</b> be
* created (eg this filter is only being used with Basic authentication or
* similar clients that will never present the same <code>jsessionid</code>
* etc), the {@link #setAllowSessionCreation(boolean)} should be set to
* <code>false</code>. Only do this if you really need to conserve server
* memory and are sure ensure all classes using the <code>ContextHolder</code>
* are designed to have no persistence of the <code>Context</code> between web
* requests.
* </p>
*
* <p>
* This filter MUST be executed BEFORE any authentication procesing mechanisms.
* Authentication processing mechanisms (eg BASIC, CAS processing filters etc)
* expect the <code>ContextHolder</code> to be contain a valid
* <code>SecureContext</code> by the time they execute.
* </p>
*
* @author Ben Alex
* @author Patrick Burleson
* @version $Id$
*/
public class HttpSessionContextIntegrationFilter implements InitializingBean,
Filter {
//~ Static fields/initializers =============================================
protected static final Log logger = LogFactory.getLog(HttpSessionContextIntegrationFilter.class);
private static final String FILTER_APPLIED = "__acegi_session_integration_filter_applied";
public static final String ACEGI_SECURITY_CONTEXT_KEY = "ACEGI_SECURITY_CONTEXT";
//~ Instance fields ========================================================
private Class context;
private Object contextObject;
/**
* Indicates if this filter can create a <code>HttpSession</code> if needed
* (sessions are always created sparingly, but setting this value to false
* will prohibit sessions from ever being created). Defaults to true.
*/
private boolean allowSessionCreation = true;
//~ Methods ================================================================
public void setAllowSessionCreation(boolean allowSessionCreation) {
this.allowSessionCreation = allowSessionCreation;
}
public boolean isAllowSessionCreation() {
return allowSessionCreation;
}
public void setContext(Class secureContext) {
this.context = secureContext;
}
public Class getContext() {
return context;
}
public void afterPropertiesSet() throws Exception {
if ((this.context == null)
|| (!Context.class.isAssignableFrom(this.context))) {
throw new IllegalArgumentException(
"context must be defined and implement Context (typically use net.sf.acegisecurity.context.security.SecureContextImpl)");
}
this.contextObject = generateNewContext();
}
/**
* Does nothing. We use IoC container lifecycle services instead.
*/
public void destroy() {}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if ((request != null) && (request.getAttribute(FILTER_APPLIED) != null)) {
// ensure that filter is only applied once per request
chain.doFilter(request, response);
} else {
if (request != null) {
request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
}
if (ContextHolder.getContext() != null) {
if (logger.isWarnEnabled()) {
logger.warn(
"ContextHolder should have been null but contained: '"
+ ContextHolder.getContext() + "'; setting to null now");
}
ContextHolder.setContext(null);
}
HttpSession httpSession = null;
try {
httpSession = ((HttpServletRequest) request).getSession(false);
} catch (IllegalStateException ignored) {}
if (httpSession != null) {
Object contextObject = httpSession.getAttribute(ACEGI_SECURITY_CONTEXT_KEY);
if (contextObject != null) {
if (contextObject instanceof Context) {
if (logger.isDebugEnabled()) {
logger.debug(
"Obtained from ACEGI_SECURITY_CONTEXT a valid Context and set to ContextHolder: '"
+ contextObject + "'");
}
ContextHolder.setContext((Context) contextObject);
} else {
if (logger.isWarnEnabled()) {
logger.warn(
"ACEGI_SECURITY_CONTEXT did not contain a Context but contained: '"
+ contextObject
+ "'; are you improperly modifying the HttpSession directly (you should always use ContextHolder) or using the HttpSession attribute reserved for this class?");
}
}
} else {
if (logger.isDebugEnabled()) {
logger.debug(
"HttpSession returned null object for ACEGI_SECURITY_CONTEXT");
}
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("No HttpSession currently exists");
}
}
if (ContextHolder.getContext() == null) {
ContextHolder.setContext(generateNewContext());
if (logger.isDebugEnabled()) {
logger.debug(
"As ContextHolder null, setup ContextHolder with a fresh new instance: '"
+ ContextHolder.getContext() + "'");
}
}
// Proceed with chain
chain.doFilter(request, response);
// Store context back to HttpSession
try {
httpSession = ((HttpServletRequest) request).getSession(false);
} catch (IllegalStateException ignored) {}
// Generate a HttpSession only if we need to
if (httpSession == null) {
if (!allowSessionCreation) {
if (logger.isDebugEnabled()) {
logger.debug(
"Whilst ContextHolder contents have changed, the HttpSessionContextIntegrationFilter is prohibited from creating a HttpSession by the allowSessionCreation property being false");
}
} else if (!contextObject.equals(ContextHolder.getContext())) {
if (logger.isDebugEnabled()) {
logger.debug(
"HttpSession being created as ContextHolder contents are non-default");
}
try {
httpSession = ((HttpServletRequest) request).getSession(true);
} catch (IllegalStateException ignored) {}
} else {
if (logger.isDebugEnabled()) {
logger.debug(
"HttpSession still null, but ContextHolder has not changed from default: ' "
+ ContextHolder.getContext()
+ "'; not creating HttpSession or storing ContextHolder contents");
}
}
}
// If HttpSession exists, store current ContextHolder contents
if (httpSession != null) {
httpSession.setAttribute(ACEGI_SECURITY_CONTEXT_KEY,
ContextHolder.getContext());
if (logger.isDebugEnabled()) {
logger.debug("Context stored to HttpSession: '"
+ ContextHolder.getContext() + "'");
}
}
// Remove ContextHolder contents
ContextHolder.setContext(null);
if (logger.isDebugEnabled()) {
logger.debug(
"ContextHolder set to null as request processing completed");
}
}
}
public Context generateNewContext() throws ServletException {
try {
return (Context) this.context.newInstance();
} catch (InstantiationException ie) {
throw new ServletException(ie);
} catch (IllegalAccessException iae) {
throw new ServletException(iae);
}
}
/**
* Does nothing. We use IoC container lifecycle services instead.
*
* @param filterConfig ignored
*
* @throws ServletException ignored
*/
public void init(FilterConfig filterConfig) throws ServletException {}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -13,12 +13,12 @@
* limitations under the License. * limitations under the License.
*/ */
package net.sf.acegisecurity.ui.httpinvoker; package net.sf.acegisecurity.context.httpinvoker;
import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.AuthenticationCredentialsNotFoundException; import net.sf.acegisecurity.AuthenticationCredentialsNotFoundException;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.security.SecureContext;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -13,7 +13,7 @@
* limitations under the License. * limitations under the License.
*/ */
package net.sf.acegisecurity.ui.rmi; package net.sf.acegisecurity.context.rmi;
import net.sf.acegisecurity.context.Context; import net.sf.acegisecurity.context.Context;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
@ -34,10 +34,10 @@ import java.lang.reflect.InvocationTargetException;
* *
* <p> * <p>
* When constructed on the client via {@link * When constructed on the client via {@link
* net.sf.acegisecurity.ui.rmi.ContextPropagatingRemoteInvocationFactory}, the * net.sf.acegisecurity.context.rmi.ContextPropagatingRemoteInvocationFactory},
* contents of the <code>ContextHolder</code> are stored inside the object. * the contents of the <code>ContextHolder</code> are stored inside the
* The object is then passed to the server that is processing the remote * object. The object is then passed to the server that is processing the
* invocation. Upon the server invoking the remote invocation, it will * remote invocation. Upon the server invoking the remote invocation, it will
* retrieve the passed contents of the <code>ContextHolder</code> and set them * retrieve the passed contents of the <code>ContextHolder</code> and set them
* to the server-side <code>ContextHolder</code> whilst the target object is * to the server-side <code>ContextHolder</code> whilst the target object is
* invoked. When the target invocation has been completed, the server-side * invoked. When the target invocation has been completed, the server-side

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -13,7 +13,7 @@
* limitations under the License. * limitations under the License.
*/ */
package net.sf.acegisecurity.ui.rmi; package net.sf.acegisecurity.context.rmi;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -13,9 +13,10 @@
* limitations under the License. * limitations under the License.
*/ */
package net.sf.acegisecurity.context; package net.sf.acegisecurity.context.security;
import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.context.Context;
/** /**

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -13,9 +13,11 @@
* limitations under the License. * limitations under the License.
*/ */
package net.sf.acegisecurity.context; package net.sf.acegisecurity.context.security;
import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.context.ContextImpl;
import net.sf.acegisecurity.context.ContextInvalidException;
/** /**
@ -39,6 +41,25 @@ public class SecureContextImpl extends ContextImpl implements SecureContext {
return this.authentication; return this.authentication;
} }
public boolean equals(Object obj) {
if (obj instanceof SecureContextImpl) {
SecureContextImpl test = (SecureContextImpl) obj;
if ((this.getAuthentication() == null)
&& (test.getAuthentication() == null)) {
return true;
}
if ((this.getAuthentication() != null)
&& (test.getAuthentication() != null)
&& this.getAuthentication().equals(test.getAuthentication())) {
return true;
}
}
return false;
}
public String toString() { public String toString() {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
sb.append(super.toString()); sb.append(super.toString());

View File

@ -0,0 +1,45 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.acegisecurity.context.security;
import net.sf.acegisecurity.context.ContextHolder;
/**
* A simple static method for quickly accessing the <code>SecureContext</code>.
*
* <p>
* Expects the <code>ContextHolder</code> to be populated and contain a valid
* <code>SecureContext</code>.
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public class SecureContextUtils {
//~ Methods ================================================================
public static SecureContext getSecureContext() {
if ((ContextHolder.getContext() == null)
|| !(ContextHolder.getContext() instanceof SecureContext)) {
throw new IllegalStateException("ContextHolder invalid: '"
+ ContextHolder.getContext()
+ "': are your filters ordered correctly? HttpSessionContextIntegrationFilter should have already executed by this time (look for it in the stack dump below)");
}
return (SecureContext) ContextHolder.getContext();
}
}

View File

@ -0,0 +1,7 @@
<html>
<body>
Provides a <code>Context</code> that is designed to be compatible with
Acegi Security.
</body>
</html>

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -27,7 +27,7 @@ import net.sf.acegisecurity.ConfigAttributeDefinition;
import net.sf.acegisecurity.RunAsManager; import net.sf.acegisecurity.RunAsManager;
import net.sf.acegisecurity.context.Context; import net.sf.acegisecurity.context.Context;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.intercept.event.AuthenticationCredentialsNotFoundEvent; import net.sf.acegisecurity.intercept.event.AuthenticationCredentialsNotFoundEvent;
import net.sf.acegisecurity.intercept.event.AuthenticationFailureEvent; import net.sf.acegisecurity.intercept.event.AuthenticationFailureEvent;
import net.sf.acegisecurity.intercept.event.AuthorizationFailureEvent; import net.sf.acegisecurity.intercept.event.AuthorizationFailureEvent;
@ -104,7 +104,6 @@ import java.util.Set;
* object, return the <code>ContextHolder</code> to the object that existed * object, return the <code>ContextHolder</code> to the object that existed
* after the call to <code>AuthenticationManager</code>. * after the call to <code>AuthenticationManager</code>.
* </li> * </li>
*
* <li> * <li>
* If an <code>AfterInvocationManager</code> is defined, invoke the invocation * If an <code>AfterInvocationManager</code> is defined, invoke the invocation
* manager and allow it to replace the object due to be returned to the * manager and allow it to replace the object due to be returned to the

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,7 +20,7 @@ import net.sf.acegisecurity.acl.AclEntry;
import net.sf.acegisecurity.acl.AclManager; import net.sf.acegisecurity.acl.AclManager;
import net.sf.acegisecurity.acl.basic.AbstractBasicAclEntry; import net.sf.acegisecurity.acl.basic.AbstractBasicAclEntry;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.security.SecureContext;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,7 +18,7 @@ package net.sf.acegisecurity.taglibs.authz;
import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.UserDetails; import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.security.SecureContext;
import java.io.IOException; import java.io.IOException;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,14 +18,15 @@ package net.sf.acegisecurity.taglibs.authz;
import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.GrantedAuthorityImpl; import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.security.SecureContext;
import org.springframework.web.util.ExpressionEvaluationUtils;
import java.util.*;
import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.Tag; import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport; import javax.servlet.jsp.tagext.TagSupport;
import java.util.*;
import org.springframework.web.util.ExpressionEvaluationUtils;
/** /**
@ -70,19 +71,18 @@ public class AuthorizeTag extends TagSupport {
public int doStartTag() throws JspException { public int doStartTag() throws JspException {
if (((null == ifAllGranted) || "".equals(ifAllGranted)) if (((null == ifAllGranted) || "".equals(ifAllGranted))
&& ((null == ifAnyGranted) || "".equals(ifAnyGranted)) && ((null == ifAnyGranted) || "".equals(ifAnyGranted))
&& ((null == ifNotGranted) || "".equals(ifNotGranted))) { && ((null == ifNotGranted) || "".equals(ifNotGranted))) {
return Tag.SKIP_BODY; return Tag.SKIP_BODY;
} }
final Collection granted = getPrincipalAuthorities(); final Collection granted = getPrincipalAuthorities();
final String evaledIfNotGranted = final String evaledIfNotGranted = ExpressionEvaluationUtils
ExpressionEvaluationUtils.evaluateString( .evaluateString("ifNotGranted", ifNotGranted, pageContext);
"ifNotGranted", ifNotGranted, pageContext);
if ((null != evaledIfNotGranted) && !"".equals(evaledIfNotGranted)) { if ((null != evaledIfNotGranted) && !"".equals(evaledIfNotGranted)) {
Set grantedCopy = retainAll( Set grantedCopy = retainAll(granted,
granted,
parseAuthoritiesString(evaledIfNotGranted)); parseAuthoritiesString(evaledIfNotGranted));
if (!grantedCopy.isEmpty()) { if (!grantedCopy.isEmpty()) {
@ -90,22 +90,20 @@ public class AuthorizeTag extends TagSupport {
} }
} }
final String evaledIfAllGranted = final String evaledIfAllGranted = ExpressionEvaluationUtils
ExpressionEvaluationUtils.evaluateString( .evaluateString("ifAllGranted", ifAllGranted, pageContext);
"ifAllGranted", ifAllGranted, pageContext);
if ((null != evaledIfAllGranted) && !"".equals(evaledIfAllGranted)) { if ((null != evaledIfAllGranted) && !"".equals(evaledIfAllGranted)) {
if (!granted.containsAll( if (!granted.containsAll(parseAuthoritiesString(evaledIfAllGranted))) {
parseAuthoritiesString(evaledIfAllGranted))) {
return Tag.SKIP_BODY; return Tag.SKIP_BODY;
} }
} }
final String evaledIfAnyGranted = final String evaledIfAnyGranted = ExpressionEvaluationUtils
ExpressionEvaluationUtils.evaluateString( .evaluateString("ifAnyGranted", ifAnyGranted, pageContext);
"ifAnyGranted", ifAnyGranted, pageContext);
if ((null != evaledIfAnyGranted) && !"".equals(evaledIfAnyGranted)) { if ((null != evaledIfAnyGranted) && !"".equals(evaledIfAnyGranted)) {
Set grantedCopy = retainAll( Set grantedCopy = retainAll(granted,
granted,
parseAuthoritiesString(evaledIfAnyGranted)); parseAuthoritiesString(evaledIfAnyGranted));
if (grantedCopy.isEmpty()) { if (grantedCopy.isEmpty()) {
@ -148,7 +146,7 @@ public class AuthorizeTag extends TagSupport {
} }
private Set retainAll(final Collection granted, private Set retainAll(final Collection granted,
final Set requiredAuthorities) { final Set requiredAuthorities) {
Set grantedCopy = new HashSet(granted); Set grantedCopy = new HashSet(granted);
grantedCopy.retainAll(requiredAuthorities); grantedCopy.retainAll(requiredAuthorities);

View File

@ -1,232 +0,0 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.acegisecurity.ui;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.context.Context;
import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext;
import net.sf.acegisecurity.context.SecureContextImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* Automatically populates a {@link net.sf.acegisecurity.context.SecureContext}
* from a subclass-provided <code>Authentication</code> object.
*
* <p>
* The container hosting the Acegi Security System for Spring secured
* application is expected to expose an {@link Authentication} object in a
* well-known location. The <code>Authentication</code> object will have been
* created by the Acegi Security System for Spring and placed into the
* well-known location via approaches such as container adapters or container
* sessions.
* </p>
*
* <P>
* Once the <code>Authentication</code> object has been extracted from the
* well-known location, the <code>AbstractIntegrationFilter</code> handles
* putting it into the {@link ContextHolder}. It then removes it once the
* filter chain has completed.
* </p>
*
* <p>
* This filter will not abort if an <code>Authentication</code> object cannot
* be obtained from the well-known location. It will simply continue the
* filter chain as normal.
* </p>
*
* <p>
* If the <code>ContextHolder</code> does not contain a valid {@link
* SecureContext}, one will be created. The created object will be of the
* instance defined by the {@link #setSecureContext(Class)} method.
* </p>
*
* <P>
* This filter will only execute once per request, to resolve servlet container
* (specifically Weblogic) incompatibilities.
* </p>
*
* @author Ben Alex
* @author Patrick Burleson
* @version $Id$
*/
public abstract class AbstractIntegrationFilter implements InitializingBean,
Filter {
//~ Static fields/initializers =============================================
protected static final Log logger = LogFactory.getLog(AbstractIntegrationFilter.class);
private static final String FILTER_APPLIED = "__acegi_integration_filterapplied";
//~ Instance fields ========================================================
private Class secureContext = SecureContextImpl.class;
//~ Methods ================================================================
public void setSecureContext(Class secureContext) {
this.secureContext = secureContext;
}
public Class getSecureContext() {
return secureContext;
}
public void afterPropertiesSet() throws Exception {
if ((this.secureContext == null)
|| (!SecureContext.class.isAssignableFrom(this.secureContext))) {
throw new IllegalArgumentException(
"secureContext must be defined and implement SecureContext");
}
}
/**
* Writes a new <code>Authentication</code> object to the container's
* well-known location, if supported the subclass.
*
* @param request which may be required by the implementing method to
* access the well-known location for the current principal
* @param authentication the new object to be written to the container
*/
public abstract void commitToContainer(ServletRequest request,
Authentication authentication);
public void destroy() {}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if ((request != null) && (request.getAttribute(FILTER_APPLIED) != null)) {
// ensure that filter is only applied once per request
chain.doFilter(request, response);
} else {
if (request != null) {
request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
}
// Populate authentication information
Object extracted = this.extractFromContainer(request);
if (extracted instanceof Authentication) {
if (logger.isDebugEnabled()) {
logger.debug("Authentication '" + extracted
+ "' added to ContextHolder from container");
}
Authentication auth = (Authentication) extracted;
// Get or create existing SecureContext
SecureContext sc = null;
if ((ContextHolder.getContext() == null)
|| !(ContextHolder.getContext() instanceof SecureContext)) {
try {
sc = (SecureContext) this.secureContext.newInstance();
} catch (InstantiationException ie) {
throw new ServletException(ie);
} catch (IllegalAccessException iae) {
throw new ServletException(iae);
}
} else {
sc = (SecureContext) ContextHolder.getContext();
}
// Add Authentication to SecureContext, and save
sc.setAuthentication(auth);
ContextHolder.setContext((Context) sc);
} else {
if (logger.isDebugEnabled()) {
logger.debug(
"Authentication not added to ContextHolder (could not extract an authentication object from the container which is an instance of Authentication)");
}
}
// Proceed with chain
chain.doFilter(request, response);
// Remove authentication information
if ((ContextHolder.getContext() != null)
&& ContextHolder.getContext() instanceof SecureContext) {
// Get context holder
SecureContext secureContext = (SecureContext) ContextHolder
.getContext();
if (logger.isDebugEnabled()) {
logger.debug(
"Updating container with new Authentication object ('"
+ secureContext.getAuthentication()
+ "'), and then removing Authentication from ContextHolder");
}
// Update container with new Authentication object (may have been updated during method invocation)
this.commitToContainer(request,
secureContext.getAuthentication());
// Remove authentication information from ContextHolder
secureContext.setAuthentication(null);
ContextHolder.setContext((Context) secureContext);
} else {
if (logger.isDebugEnabled()) {
logger.debug(
"ContextHolder does not contain any authentication information");
}
}
}
}
/**
* Subclasses must override this method to provide the <code>Object</code>
* that contains the <code>Authentication</code> interface.
*
* <p>
* For convenience we have allowed any <code>Object</code> to be returned
* by subclasses, as the abstract class will ensure class casting safety
* and ignore objects that do not implement <code>Authentication</code>.
* </p>
*
* <p>
* If no <code>Authentication</code> object is available, subclasses should
* return <code>null</code>.
* </p>
*
* <p>
* If the subclass can locate multiple authentication objects, they should
* return the object that was created by the Acegi Security System for
* Spring (ie the object that implements <code>Authentication</code>).
* </p>
*
* @param request the request, which may be of use in extracting the
* authentication object
*
* @return <code>null</code> or an object that implements
* <code>Authentication</code>
*/
public abstract Object extractFromContainer(ServletRequest request);
public void init(FilterConfig filterConfig) throws ServletException {}
}

View File

@ -22,8 +22,10 @@ import net.sf.acegisecurity.AuthenticationServiceException;
import net.sf.acegisecurity.BadCredentialsException; import net.sf.acegisecurity.BadCredentialsException;
import net.sf.acegisecurity.DisabledException; import net.sf.acegisecurity.DisabledException;
import net.sf.acegisecurity.LockedException; import net.sf.acegisecurity.LockedException;
import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.context.security.SecureContextUtils;
import net.sf.acegisecurity.providers.cas.ProxyUntrustedException; import net.sf.acegisecurity.providers.cas.ProxyUntrustedException;
import net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -34,6 +36,7 @@ import java.io.IOException;
import javax.servlet.Filter; import javax.servlet.Filter;
import javax.servlet.FilterChain; import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import javax.servlet.ServletResponse;
@ -42,15 +45,13 @@ import javax.servlet.http.HttpServletResponse;
/** /**
* Abstract processor of HTTP-based authentication requests, which places the * Abstract processor of browser-based HTTP-based authentication requests.
* resulting <code>Authentication</code> object into the
* <code>HttpSession</code>.
* *
* <p> * <p>
* This filter is responsible for processing authentication requests. If * This filter is responsible for processing authentication requests. If
* authentication is successful, the resulting {@link Authentication} object * authentication is successful, the resulting {@link Authentication} object
* will be placed into the <code>HttpSession</code> with the attribute defined * will be placed into the <code>ContextHolder</code>, which is guaranteed to
* by {@link HttpSessionIntegrationFilter#ACEGI_SECURITY_AUTHENTICATION_KEY}. * have already been created by an earlier filter.
* </p> * </p>
* *
* <p> * <p>
@ -307,6 +308,9 @@ public abstract class AbstractProcessingFilter implements Filter,
} }
} }
/**
* Does nothing. We use IoC container lifecycle services instead.
*/
public void destroy() {} public void destroy() {}
public void doFilter(ServletRequest request, ServletResponse response, public void doFilter(ServletRequest request, ServletResponse response,
@ -353,6 +357,15 @@ public abstract class AbstractProcessingFilter implements Filter,
chain.doFilter(request, response); chain.doFilter(request, response);
} }
/**
* Does nothing. We use IoC container lifecycle services instead.
*
* @param arg0 ignored
*
* @throws ServletException ignored
*/
public void init(FilterConfig arg0) throws ServletException {}
protected void onPreAuthentication(HttpServletRequest request, protected void onPreAuthentication(HttpServletRequest request,
HttpServletResponse response) throws IOException {} HttpServletResponse response) throws IOException {}
@ -390,8 +403,14 @@ public abstract class AbstractProcessingFilter implements Filter,
logger.debug("Authentication success: " + authResult.toString()); logger.debug("Authentication success: " + authResult.toString());
} }
request.getSession().setAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY, SecureContext sc = SecureContextUtils.getSecureContext();
authResult); sc.setAuthentication(authResult);
if (logger.isDebugEnabled()) {
logger.debug(
"Updated ContextHolder to contain the following Authentication: '"
+ authResult + "'");
}
String targetUrl = (String) request.getSession().getAttribute(ACEGI_SECURITY_TARGET_URL_KEY); String targetUrl = (String) request.getSession().getAttribute(ACEGI_SECURITY_TARGET_URL_KEY);
request.getSession().removeAttribute(ACEGI_SECURITY_TARGET_URL_KEY); request.getSession().removeAttribute(ACEGI_SECURITY_TARGET_URL_KEY);
@ -418,6 +437,14 @@ public abstract class AbstractProcessingFilter implements Filter,
protected void unsuccessfulAuthentication(HttpServletRequest request, protected void unsuccessfulAuthentication(HttpServletRequest request,
HttpServletResponse response, AuthenticationException failed) HttpServletResponse response, AuthenticationException failed)
throws IOException { throws IOException {
SecureContext sc = SecureContextUtils.getSecureContext();
sc.setAuthentication(null);
ContextHolder.setContext(sc);
if (logger.isDebugEnabled()) {
logger.debug("Updated ContextHolder to contain null Authentication");
}
String failureUrl = authenticationFailureUrl; String failureUrl = authenticationFailureUrl;
if (failed instanceof AuthenticationServiceException if (failed instanceof AuthenticationServiceException
@ -451,7 +478,6 @@ public abstract class AbstractProcessingFilter implements Filter,
request.getSession().setAttribute(ACEGI_SECURITY_LAST_EXCEPTION_KEY, request.getSession().setAttribute(ACEGI_SECURITY_LAST_EXCEPTION_KEY,
failed); failed);
request.getSession().removeAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY);
onUnsuccessfulAuthentication(request, response); onUnsuccessfulAuthentication(request, response);

View File

@ -18,10 +18,13 @@ package net.sf.acegisecurity.ui.basicauth;
import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.AuthenticationException; import net.sf.acegisecurity.AuthenticationException;
import net.sf.acegisecurity.AuthenticationManager; import net.sf.acegisecurity.AuthenticationManager;
import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter;
import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.context.security.SecureContextUtils;
import net.sf.acegisecurity.intercept.web.AuthenticationEntryPoint; import net.sf.acegisecurity.intercept.web.AuthenticationEntryPoint;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import net.sf.acegisecurity.ui.WebAuthenticationDetails; import net.sf.acegisecurity.ui.WebAuthenticationDetails;
import net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -73,7 +76,8 @@ import javax.servlet.http.HttpServletResponse;
* <P> * <P>
* If authentication is successful, the resulting {@link Authentication} object * If authentication is successful, the resulting {@link Authentication} object
* will be placed into the <code>HttpSession</code> with the attribute defined * will be placed into the <code>HttpSession</code> with the attribute defined
* by {@link HttpSessionIntegrationFilter#ACEGI_SECURITY_AUTHENTICATION_KEY}. * by {@link
* HttpSessionContextIntegrationFilter#ACEGI_SECURITY_AUTHENTICATION_KEY}.
* </p> * </p>
* *
* <p> * <p>
@ -172,6 +176,7 @@ public class BasicProcessingFilter implements Filter, InitializingBean {
authRequest.setDetails(new WebAuthenticationDetails(httpRequest)); authRequest.setDetails(new WebAuthenticationDetails(httpRequest));
Authentication authResult; Authentication authResult;
SecureContext sc = SecureContextUtils.getSecureContext();
try { try {
authResult = authenticationManager.authenticate(authRequest); authResult = authenticationManager.authenticate(authRequest);
@ -182,6 +187,8 @@ public class BasicProcessingFilter implements Filter, InitializingBean {
+ " failed: " + failed.toString()); + " failed: " + failed.toString());
} }
sc.setAuthentication(null);
ContextHolder.setContext(sc);
authenticationEntryPoint.commence(request, response, failed); authenticationEntryPoint.commence(request, response, failed);
return; return;
@ -192,8 +199,8 @@ public class BasicProcessingFilter implements Filter, InitializingBean {
logger.debug("Authentication success: " + authResult.toString()); logger.debug("Authentication success: " + authResult.toString());
} }
httpRequest.getSession().setAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY, sc.setAuthentication(authResult);
authResult); ContextHolder.setContext(sc);
} }
chain.doFilter(request, response); chain.doFilter(request, response);

View File

@ -1,6 +1,6 @@
<html> <html>
<body> <body>
Interfaces the system with various end-user authentication approaches, such Authentication processing mechanisms, which respond to the submission of authentication
as container adapters and web applications. credentials using various protocols (eg BASIC, CAS, form login etc).
</body> </body>
</html> </html>

View File

@ -1,158 +0,0 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.acegisecurity.ui.webapp;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.ui.AbstractIntegrationFilter;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
/**
* Populates a {@link net.sf.acegisecurity.context.SecureContext} from the
* <code>HttpSession</code>.
*
* <P>
* The filter will inspect the <code>HttpSession</code> for an attribute with
* the name indicated by {@link #ACEGI_SECURITY_AUTHENTICATION_KEY}. If that
* attribute contains an instance of {@link Authentication}, it will be placed
* into the <code>ContextHolder</code>.
* </p>
*
* <P>
* This filter is normally used in conjunction with {@link
* AuthenticationProcessingFilter}, which populates the
* <code>HttpSession</code> with an <code>Authentication</code> object based
* on a form login. Similarly, the {@link
* net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter} will populate the
* <code>HttpSession</code> based on a BASIC authentication request.
* Alternatively, users may elect to use their own approach for populating the
* <code>HttpSession</code>.
* </p>
*
* <p>
* As with other <code>AbstractIntegrationFilter</code>s, this filter will
* ensure the <code>ContextHolder</code> is populated with the
* <code>Authentication</code> object for the duration of the HTTP request,
* and is unbound from the <code>ContextHolder</code> at the completion of the
* request.
* </p>
*
* <P>
* The filter can also copy the <code>Authentication</code> object to any
* number of additional <code>HttpSession</code> attributes. To use this
* capability, provide <code>String</code>s indicating the additional
* attribute name(s) to {@link #setAdditionalAttributes(List)}.
* </p>
*
* <p>
* See {@link AbstractIntegrationFilter} for further information.
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public class HttpSessionIntegrationFilter extends AbstractIntegrationFilter {
//~ Static fields/initializers =============================================
public static final String ACEGI_SECURITY_AUTHENTICATION_KEY = "ACEGI_SECURITY_AUTHENTICATION";
//~ Instance fields ========================================================
private List additionalAttributes = null;
//~ Methods ================================================================
public void setAdditionalAttributes(List additionalAttributes) {
validateList(additionalAttributes);
this.additionalAttributes = additionalAttributes;
}
public List getAdditionalAttributes() {
return additionalAttributes;
}
public void commitToContainer(ServletRequest request,
Authentication authentication) {
if (request instanceof HttpServletRequest
&& ((HttpServletRequest) request).isRequestedSessionIdValid()) {
HttpSession httpSession = ((HttpServletRequest) request).getSession(false);
if (httpSession != null) {
httpSession.setAttribute(ACEGI_SECURITY_AUTHENTICATION_KEY,
authentication);
updateOtherLocations(httpSession, authentication);
}
}
}
public Object extractFromContainer(ServletRequest request) {
if (request instanceof HttpServletRequest) {
HttpSession httpSession = null;
try {
httpSession = ((HttpServletRequest) request).getSession(false);
} catch (IllegalStateException ignored) {}
if (httpSession != null) {
Object authObject = httpSession.getAttribute(ACEGI_SECURITY_AUTHENTICATION_KEY);
if (authObject instanceof Authentication) {
updateOtherLocations(httpSession,
(Authentication) authObject);
return authObject;
}
}
}
return null;
}
private void updateOtherLocations(HttpSession session,
Authentication authentication) {
if (additionalAttributes == null) {
return;
}
Iterator iter = additionalAttributes.iterator();
while (iter.hasNext()) {
String attribute = (String) iter.next();
session.setAttribute(attribute, authentication);
}
}
private void validateList(List newAdditionalAttributes) {
if (newAdditionalAttributes != null) {
Iterator iter = newAdditionalAttributes.iterator();
while (iter.hasNext()) {
Object objectToTest = iter.next();
if (!(objectToTest instanceof String)) {
throw new IllegalArgumentException(
"List of additional attributes can only contains Strings!");
}
}
}
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -13,7 +13,7 @@
* limitations under the License. * limitations under the License.
*/ */
package net.sf.acegisecurity.ui.wrapper; package net.sf.acegisecurity.wrapper;
import java.io.IOException; import java.io.IOException;

View File

@ -13,13 +13,13 @@
* limitations under the License. * limitations under the License.
*/ */
package net.sf.acegisecurity.ui.wrapper; package net.sf.acegisecurity.wrapper;
import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.GrantedAuthority; import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.UserDetails; import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.security.SecureContext;
import java.security.Principal; import java.security.Principal;

View File

@ -15,6 +15,8 @@
package net.sf.acegisecurity; package net.sf.acegisecurity;
import org.springframework.mock.web.MockHttpSession;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
@ -315,10 +317,20 @@ public class MockHttpServletRequest implements HttpServletRequest {
} }
public HttpSession getSession(boolean arg0) { public HttpSession getSession(boolean arg0) {
if (arg0) {
if (this.session == null) {
this.session = new MockHttpSession();
}
}
return this.session; return this.session;
} }
public HttpSession getSession() { public HttpSession getSession() {
if (this.session == null) {
this.session = new MockHttpSession();
}
return this.session; return this.session;
} }

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,7 +17,7 @@ package net.sf.acegisecurity;
import net.sf.acegisecurity.context.Context; import net.sf.acegisecurity.context.Context;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.security.SecureContext;
/** /**

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,9 +17,14 @@ package net.sf.acegisecurity.adapters;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.acegisecurity.*;
import net.sf.acegisecurity.GrantedAuthority; import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl; import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.MockHttpServletRequest;
import net.sf.acegisecurity.MockHttpServletResponse;
import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.context.security.SecureContextUtils;
import net.sf.acegisecurity.util.MockFilterChain;
/** /**
@ -41,41 +46,62 @@ public class HttpRequestIntegrationFilterTests extends TestCase {
//~ Methods ================================================================ //~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
public static void main(String[] args) { public static void main(String[] args) {
junit.textui.TestRunner.run(HttpRequestIntegrationFilterTests.class); junit.textui.TestRunner.run(HttpRequestIntegrationFilterTests.class);
} }
public void testCorrectOperation() { public void testCorrectOperation() throws Exception {
HttpRequestIntegrationFilter filter = new HttpRequestIntegrationFilter(); HttpRequestIntegrationFilter filter = new HttpRequestIntegrationFilter();
PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key", PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key",
"someone", "password", "someone", "password",
new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")}); new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")});
Object result = filter.extractFromContainer(new MockHttpServletRequest(
principal, null));
if (!(result instanceof PrincipalAcegiUserToken)) { MockHttpServletRequest request = new MockHttpServletRequest(principal,
null);
MockHttpServletResponse response = new MockHttpServletResponse();
MockFilterChain chain = new MockFilterChain(true);
filter.doFilter(request, response, chain);
if (!(SecureContextUtils.getSecureContext().getAuthentication() instanceof PrincipalAcegiUserToken)) {
fail("Should have returned PrincipalAcegiUserToken"); fail("Should have returned PrincipalAcegiUserToken");
} }
PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result; PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) SecureContextUtils.getSecureContext()
assertEquals(principal, result); .getAuthentication();
assertEquals(principal, castResult);
filter.commitToContainer(new MockHttpServletRequest(principal, null),
principal);
} }
public void testHandlesIfHttpRequestIsNullForSomeReason() { public void testHandlesIfHttpRequestIsNullForSomeReason()
throws Exception {
HttpRequestIntegrationFilter filter = new HttpRequestIntegrationFilter(); HttpRequestIntegrationFilter filter = new HttpRequestIntegrationFilter();
assertEquals(null, filter.extractFromContainer(null));
try {
filter.doFilter(null, null, null);
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertTrue(true);
}
} }
public void testHandlesIfThereIsNoPrincipal() { public void testHandlesIfThereIsNoPrincipal() throws Exception {
HttpRequestIntegrationFilter filter = new HttpRequestIntegrationFilter(); HttpRequestIntegrationFilter filter = new HttpRequestIntegrationFilter();
assertEquals(null, MockHttpServletRequest request = new MockHttpServletRequest("foo");
filter.extractFromContainer(new MockHttpServletRequest(null, null))); MockHttpServletResponse response = new MockHttpServletResponse();
MockFilterChain chain = new MockFilterChain(true);
assertNull(SecureContextUtils.getSecureContext().getAuthentication());
filter.doFilter(request, response, chain);
assertNull(SecureContextUtils.getSecureContext().getAuthentication());
}
protected void setUp() throws Exception {
super.setUp();
ContextHolder.setContext(new SecureContextImpl());
}
protected void tearDown() throws Exception {
super.tearDown();
ContextHolder.setContext(null);
} }
} }

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,6 +17,8 @@ package net.sf.acegisecurity.context;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.acegisecurity.context.security.SecureContextImpl;
import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader; import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader;

View File

@ -0,0 +1,245 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.acegisecurity.context;
import junit.framework.TestCase;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.MockFilterConfig;
import net.sf.acegisecurity.MockHttpServletRequest;
import net.sf.acegisecurity.MockHttpServletResponse;
import net.sf.acegisecurity.MockHttpSession;
import net.sf.acegisecurity.adapters.PrincipalAcegiUserToken;
import net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter;
import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.context.security.SecureContextUtils;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* Tests {@link HttpSessionContextIntegrationFilter}.
*
* @author Ben Alex
* @version $Id$
*/
public class HttpSessionContextIntegrationFilterTests extends TestCase {
//~ Constructors ===========================================================
public HttpSessionContextIntegrationFilterTests() {
super();
}
public HttpSessionContextIntegrationFilterTests(String arg0) {
super(arg0);
}
//~ Methods ================================================================
public static void main(String[] args) {
junit.textui.TestRunner.run(HttpSessionContextIntegrationFilterTests.class);
}
public void testDetectsMissingOrInvalidContext() throws Exception {
HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter();
try {
filter.afterPropertiesSet();
fail("Shown have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertTrue(true);
}
try {
filter.setContext(Integer.class);
assertEquals(Integer.class, filter.getContext());
filter.afterPropertiesSet();
fail("Shown have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertTrue(true);
}
}
public void testExistingContextContentsCopiedIntoContextHolderFromSessionAndChangesToContextCopiedBackToSession()
throws Exception {
// Build an Authentication object we simulate came from HttpSession
PrincipalAcegiUserToken sessionPrincipal = new PrincipalAcegiUserToken("key",
"someone", "password",
new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")});
// Build an Authentication object we simulate our Authentication changed it to
PrincipalAcegiUserToken updatedPrincipal = new PrincipalAcegiUserToken("key",
"someone", "password",
new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_DIFFERENT_ROLE")});
// Build a Context to store in HttpSession (simulating prior request)
SecureContext sc = new SecureContextImpl();
sc.setAuthentication(sessionPrincipal);
// Build a mock request
MockHttpSession session = new MockHttpSession();
session.setAttribute(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY,
sc);
MockHttpServletRequest request = new MockHttpServletRequest(null,
session);
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain chain = new MockFilterChain(sessionPrincipal,
updatedPrincipal);
// Prepare filter
HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter();
filter.setContext(SecureContextImpl.class);
filter.afterPropertiesSet();
// Execute filter
executeFilterInContainerSimulator(new MockFilterConfig(), filter,
request, response, chain);
// Obtain new/update Authentication from HttpSession
Context context = (Context) session.getAttribute(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY);
assertEquals(updatedPrincipal,
((SecureContext) context).getAuthentication());
}
public void testHttpSessionCreatedWhenContextHolderChanges()
throws Exception {
// Build an Authentication object we simulate our Authentication changed it to
PrincipalAcegiUserToken updatedPrincipal = new PrincipalAcegiUserToken("key",
"someone", "password",
new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_DIFFERENT_ROLE")});
// Build a mock request
MockHttpSession session = null;
MockHttpServletRequest request = new MockHttpServletRequest(null,
session);
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain chain = new MockFilterChain(null, updatedPrincipal);
// Prepare filter
HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter();
filter.setContext(SecureContextImpl.class);
filter.afterPropertiesSet();
// Execute filter
executeFilterInContainerSimulator(new MockFilterConfig(), filter,
request, response, chain);
// Obtain new/update Authentication from HttpSession
Context context = (Context) request.getSession().getAttribute(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY);
assertEquals(updatedPrincipal,
((SecureContext) context).getAuthentication());
}
public void testHttpSessionNotCreatedUnlessContextHolderChanges()
throws Exception {
// Build a mock request
MockHttpServletRequest request = new MockHttpServletRequest(null, null);
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain chain = new MockFilterChain(null, null);
// Prepare filter
HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter();
filter.setContext(SecureContextImpl.class);
filter.afterPropertiesSet();
// Execute filter
executeFilterInContainerSimulator(new MockFilterConfig(), filter,
request, response, chain);
// Obtain new/update Authentication from HttpSession
assertNull(request.getSession(false));
}
public void testHttpSessionWithNonContextInWellKnownLocationIsOverwritten()
throws Exception {
// Build an Authentication object we simulate our Authentication changed it to
PrincipalAcegiUserToken updatedPrincipal = new PrincipalAcegiUserToken("key",
"someone", "password",
new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_DIFFERENT_ROLE")});
// Build a mock request
MockHttpSession session = new MockHttpSession();
session.setAttribute(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY,
"NOT_A_CONTEXT_OBJECT");
MockHttpServletRequest request = new MockHttpServletRequest(null,
session);
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain chain = new MockFilterChain(null, updatedPrincipal);
// Prepare filter
HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter();
filter.setContext(SecureContextImpl.class);
filter.afterPropertiesSet();
// Execute filter
executeFilterInContainerSimulator(new MockFilterConfig(), filter,
request, response, chain);
// Obtain new/update Authentication from HttpSession
Context context = (Context) session.getAttribute(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY);
assertEquals(updatedPrincipal,
((SecureContext) context).getAuthentication());
}
private void executeFilterInContainerSimulator(FilterConfig filterConfig,
Filter filter, ServletRequest request, ServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
filter.init(filterConfig);
filter.doFilter(request, response, filterChain);
filter.destroy();
}
//~ Inner Classes ==========================================================
private class MockFilterChain extends TestCase implements FilterChain {
private Authentication changeContextHolder;
private Authentication expectedOnContextHolder;
public MockFilterChain(Authentication expectedOnContextHolder,
Authentication changeContextHolder) {
this.expectedOnContextHolder = expectedOnContextHolder;
this.changeContextHolder = changeContextHolder;
}
private MockFilterChain() {}
public void doFilter(ServletRequest arg0, ServletResponse arg1)
throws IOException, ServletException {
if (expectedOnContextHolder != null) {
assertEquals(expectedOnContextHolder,
SecureContextUtils.getSecureContext().getAuthentication());
}
if (changeContextHolder != null) {
SecureContext sc = SecureContextUtils.getSecureContext();
sc.setAuthentication(changeContextHolder);
ContextHolder.setContext(sc);
}
}
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,6 +18,8 @@ package net.sf.acegisecurity.context;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -13,14 +13,15 @@
* limitations under the License. * limitations under the License.
*/ */
package net.sf.acegisecurity.ui.httpinvoker; package net.sf.acegisecurity.context.httpinvoker;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor;
import net.sf.acegisecurity.context.SecureContextImpl; import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import java.io.IOException; import java.io.IOException;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -13,7 +13,7 @@
* limitations under the License. * limitations under the License.
*/ */
package net.sf.acegisecurity.ui.rmi; package net.sf.acegisecurity.context.rmi;
import junit.framework.TestCase; import junit.framework.TestCase;
@ -21,8 +21,10 @@ import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.MockMethodInvocation; import net.sf.acegisecurity.MockMethodInvocation;
import net.sf.acegisecurity.TargetObject; import net.sf.acegisecurity.TargetObject;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.rmi.ContextPropagatingRemoteInvocation;
import net.sf.acegisecurity.context.SecureContextImpl; import net.sf.acegisecurity.context.rmi.ContextPropagatingRemoteInvocationFactory;
import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,8 +28,8 @@ import net.sf.acegisecurity.SecurityConfig;
import net.sf.acegisecurity.TargetObject; import net.sf.acegisecurity.TargetObject;
import net.sf.acegisecurity.acl.basic.SomeDomain; import net.sf.acegisecurity.acl.basic.SomeDomain;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.context.SecureContextImpl; import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -35,8 +35,8 @@ import net.sf.acegisecurity.MockRunAsManager;
import net.sf.acegisecurity.RunAsManager; import net.sf.acegisecurity.RunAsManager;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.ContextImpl; import net.sf.acegisecurity.context.ContextImpl;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.context.SecureContextImpl; import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.intercept.method.AbstractMethodDefinitionSource; import net.sf.acegisecurity.intercept.method.AbstractMethodDefinitionSource;
import net.sf.acegisecurity.intercept.method.MockMethodDefinitionSource; import net.sf.acegisecurity.intercept.method.MockMethodDefinitionSource;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -27,8 +27,8 @@ import net.sf.acegisecurity.MockJoinPoint;
import net.sf.acegisecurity.MockRunAsManager; import net.sf.acegisecurity.MockRunAsManager;
import net.sf.acegisecurity.TargetObject; import net.sf.acegisecurity.TargetObject;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.context.SecureContextImpl; import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.intercept.method.MethodDefinitionMap; import net.sf.acegisecurity.intercept.method.MethodDefinitionMap;
import net.sf.acegisecurity.intercept.method.MethodDefinitionSourceEditor; import net.sf.acegisecurity.intercept.method.MethodDefinitionSourceEditor;
import net.sf.acegisecurity.providers.TestingAuthenticationToken; import net.sf.acegisecurity.providers.TestingAuthenticationToken;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -34,8 +34,8 @@ import net.sf.acegisecurity.MockRunAsManager;
import net.sf.acegisecurity.RunAsManager; import net.sf.acegisecurity.RunAsManager;
import net.sf.acegisecurity.SecurityConfig; import net.sf.acegisecurity.SecurityConfig;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.context.SecureContextImpl; import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import java.io.IOException; import java.io.IOException;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -26,8 +26,8 @@ import net.sf.acegisecurity.acl.AclManager;
import net.sf.acegisecurity.acl.basic.MockAclObjectIdentity; import net.sf.acegisecurity.acl.basic.MockAclObjectIdentity;
import net.sf.acegisecurity.acl.basic.SimpleAclEntry; import net.sf.acegisecurity.acl.basic.SimpleAclEntry;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.context.SecureContextImpl; import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.providers.TestingAuthenticationToken; import net.sf.acegisecurity.providers.TestingAuthenticationToken;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,8 +20,8 @@ import junit.framework.TestCase;
import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.GrantedAuthority; import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.context.SecureContextImpl; import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.providers.TestingAuthenticationToken; import net.sf.acegisecurity.providers.TestingAuthenticationToken;
import net.sf.acegisecurity.providers.dao.User; import net.sf.acegisecurity.providers.dao.User;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,7 +20,7 @@ import junit.framework.TestCase;
import net.sf.acegisecurity.GrantedAuthority; import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl; import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContextImpl; import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.providers.TestingAuthenticationToken; import net.sf.acegisecurity.providers.TestingAuthenticationToken;
import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspException;

View File

@ -1,16 +1,34 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.acegisecurity.taglibs.authz; package net.sf.acegisecurity.taglibs.authz;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.acegisecurity.GrantedAuthority; import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl; import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContextImpl; import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.providers.TestingAuthenticationToken; import net.sf.acegisecurity.providers.TestingAuthenticationToken;
import org.springframework.mock.web.MockPageContext; import org.springframework.mock.web.MockPageContext;
import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.Tag; import javax.servlet.jsp.tagext.Tag;
/** /**
* Test case to implement commons-el expression language expansion. * Test case to implement commons-el expression language expansion.
*/ */
@ -18,40 +36,37 @@ public class AuthorizeTagExpressionLanguageTests extends TestCase {
//~ Instance fields ======================================================== //~ Instance fields ========================================================
private final AuthorizeTag authorizeTag = new AuthorizeTag(); private final AuthorizeTag authorizeTag = new AuthorizeTag();
private MockPageContext pageContext;
private SecureContextImpl context; private SecureContextImpl context;
private TestingAuthenticationToken currentUser; private TestingAuthenticationToken currentUser;
private MockPageContext pageContext;
//~ Methods ================================================================ //~ Methods ================================================================
public void testAllGrantedUsesExpressionLanguageWhenExpressionIsEL() public void testAllGrantedUsesExpressionLanguageWhenExpressionIsEL()
throws JspException { throws JspException {
pageContext.setAttribute("authority", "ROLE_TELLER"); pageContext.setAttribute("authority", "ROLE_TELLER");
authorizeTag.setIfAllGranted("${authority}"); authorizeTag.setIfAllGranted("${authority}");
assertEquals( assertEquals("allows body - authority var contains ROLE_TELLER",
"allows body - authority var contains ROLE_TELLER", Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag());
Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag());
} }
public void testAnyGrantedUsesExpressionLanguageWhenExpressionIsEL() public void testAnyGrantedUsesExpressionLanguageWhenExpressionIsEL()
throws JspException { throws JspException {
pageContext.setAttribute("authority", "ROLE_TELLER"); pageContext.setAttribute("authority", "ROLE_TELLER");
authorizeTag.setIfAnyGranted("${authority}"); authorizeTag.setIfAnyGranted("${authority}");
assertEquals( assertEquals("allows body - authority var contains ROLE_TELLER",
"allows body - authority var contains ROLE_TELLER", Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag());
Tag.EVAL_BODY_INCLUDE, authorizeTag.doStartTag());
} }
public void testNotGrantedUsesExpressionLanguageWhenExpressionIsEL() public void testNotGrantedUsesExpressionLanguageWhenExpressionIsEL()
throws JspException { throws JspException {
pageContext.setAttribute("authority", "ROLE_TELLER"); pageContext.setAttribute("authority", "ROLE_TELLER");
authorizeTag.setIfNotGranted("${authority}"); authorizeTag.setIfNotGranted("${authority}");
assertEquals( assertEquals("allows body - authority var contains ROLE_TELLER",
"allows body - authority var contains ROLE_TELLER", Tag.SKIP_BODY, authorizeTag.doStartTag());
Tag.SKIP_BODY, authorizeTag.doStartTag());
} }
protected void setUp() throws Exception { protected void setUp() throws Exception {
@ -60,11 +75,8 @@ public class AuthorizeTagExpressionLanguageTests extends TestCase {
pageContext = new MockPageContext(); pageContext = new MockPageContext();
authorizeTag.setPageContext(pageContext); authorizeTag.setPageContext(pageContext);
currentUser = new TestingAuthenticationToken( currentUser = new TestingAuthenticationToken("abc", "123",
"abc", "123", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_TELLER"),});
new GrantedAuthority[]{
new GrantedAuthorityImpl("ROLE_TELLER"),
});
context = new SecureContextImpl(); context = new SecureContextImpl();
context.setAuthentication(currentUser); context.setAuthentication(currentUser);

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,7 +20,7 @@ import junit.framework.TestCase;
import net.sf.acegisecurity.GrantedAuthority; import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl; import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContextImpl; import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.providers.TestingAuthenticationToken; import net.sf.acegisecurity.providers.TestingAuthenticationToken;
import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspException;

View File

@ -1,308 +0,0 @@
/* Copyright 2004 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.acegisecurity.ui;
import junit.framework.TestCase;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.adapters.MockPrincipal;
import net.sf.acegisecurity.adapters.PrincipalAcegiUserToken;
import net.sf.acegisecurity.context.Context;
import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext;
import net.sf.acegisecurity.context.SecureContextImpl;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* Tests {@link AbstractIntegrationFilter}.
*
* @author Ben Alex
* @version $Id$
*/
public class AbstractIntegrationFilterTests extends TestCase {
//~ Constructors ===========================================================
public AbstractIntegrationFilterTests() {
super();
}
public AbstractIntegrationFilterTests(String arg0) {
super(arg0);
}
//~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
public static void main(String[] args) {
junit.textui.TestRunner.run(AbstractIntegrationFilterTests.class);
}
public void testContextHolderContentsPreserved() throws Exception {
PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key",
"someone", "password",
new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")});
MockAbstractIntegrationFilterImpl filter = new MockAbstractIntegrationFilterImpl(principal);
MockFilterChain chain = new MockFilterChain(true, principal);
MockSecureContextImpl secureContext = new MockSecureContextImpl(
"FOO_BAR");
ContextHolder.setContext(secureContext);
assertEquals(secureContext, ContextHolder.getContext());
executeFilterInContainerSimulator(filter, null, null, chain);
MockSecureContextImpl after = (MockSecureContextImpl) ContextHolder
.getContext();
assertEquals(secureContext.getInfo(), after.getInfo());
ContextHolder.setContext(null);
}
public void testContextHolderHasAuthenticationRemoved()
throws Exception {
PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key",
"someone", "password",
new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")});
MockAbstractIntegrationFilterImpl filter = new MockAbstractIntegrationFilterImpl(principal);
MockFilterChain chain = new MockFilterChain(true, principal);
SecureContext secureContext = new SecureContextImpl();
secureContext.setAuthentication(principal);
ContextHolder.setContext(secureContext);
assertEquals(secureContext, ContextHolder.getContext());
executeFilterInContainerSimulator(filter, null, null, chain);
SecureContext after = (SecureContext) ContextHolder.getContext();
assertEquals(null, after.getAuthentication());
ContextHolder.setContext(null);
}
public void testIgnoredWhenConcreteClassReturnsANonAuthenticationObject()
throws Exception {
MockPrincipal principal = new MockPrincipal();
MockAbstractIntegrationFilterImpl filter = new MockAbstractIntegrationFilterImpl(principal);
MockFilterChain chain = new MockFilterChain(false, null);
Context before = ContextHolder.getContext();
if (before != null) {
if (before instanceof SecureContext) {
assertEquals(null, ((SecureContext) before).getAuthentication());
}
}
executeFilterInContainerSimulator(filter, null, null, chain);
Context after = ContextHolder.getContext();
if (after != null) {
if (after instanceof SecureContext) {
assertEquals(null, ((SecureContext) after).getAuthentication());
}
}
}
public void testIgnoredWhenConcreteClassReturnsNullAuthenticationObject()
throws Exception {
MockAbstractIntegrationFilterImpl filter = new MockAbstractIntegrationFilterImpl(null);
MockFilterChain chain = new MockFilterChain(false, null);
Context before = ContextHolder.getContext();
if (before != null) {
if (before instanceof SecureContext) {
assertEquals(null, ((SecureContext) before).getAuthentication());
}
}
executeFilterInContainerSimulator(filter, null, null, chain);
Context after = ContextHolder.getContext();
if (after != null) {
if (after instanceof SecureContext) {
assertEquals(null, ((SecureContext) after).getAuthentication());
}
}
}
public void testRejectsInvalidSecureContextClass()
throws Exception {
MockAbstractIntegrationFilterImpl filter = new MockAbstractIntegrationFilterImpl(null);
// Test rejects classes not implementing SecureContext
filter.setSecureContext(String.class);
try {
filter.afterPropertiesSet();
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertTrue(true);
}
// Test accepts classes implementing SecureContext
filter.setSecureContext(SecureContextImpl.class);
filter.afterPropertiesSet();
assertTrue(true);
// Test rejects null
filter.setSecureContext(null);
try {
filter.afterPropertiesSet();
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertTrue(true);
}
}
public void testSecureContextSettersGetters() throws Exception {
MockAbstractIntegrationFilterImpl filter = new MockAbstractIntegrationFilterImpl(null);
// check the default
assertEquals(SecureContextImpl.class, filter.getSecureContext());
// check the setter
filter.setSecureContext(null);
assertNull(filter.getSecureContext());
}
public void testSuccessWhenConcreteClassReturnsValidAuthenticationObject()
throws Exception {
PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key",
"someone", "password",
new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")});
MockAbstractIntegrationFilterImpl filter = new MockAbstractIntegrationFilterImpl(principal);
MockFilterChain chain = new MockFilterChain(true, principal);
Context before = ContextHolder.getContext();
if (before != null) {
if (before instanceof SecureContext) {
assertEquals(null, ((SecureContext) before).getAuthentication());
}
}
executeFilterInContainerSimulator(filter, null, null, chain);
Context after = ContextHolder.getContext();
if (after != null) {
if (after instanceof SecureContext) {
assertEquals(null, ((SecureContext) after).getAuthentication());
}
}
}
private void executeFilterInContainerSimulator(Filter filter,
ServletRequest request, ServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
filter.init(null);
filter.doFilter(request, response, filterChain);
filter.destroy();
}
//~ Inner Classes ==========================================================
private class MockAbstractIntegrationFilterImpl
extends AbstractIntegrationFilter {
private Object extractFromContainerResult;
public MockAbstractIntegrationFilterImpl(
Object extractFromContainerResult) {
this.extractFromContainerResult = extractFromContainerResult;
}
private MockAbstractIntegrationFilterImpl() {
super();
}
public void commitToContainer(ServletRequest request,
Authentication authentication) {
this.extractFromContainerResult = authentication;
}
public Object extractFromContainer(ServletRequest request) {
return this.extractFromContainerResult;
}
}
private class MockFilterChain implements FilterChain {
private Authentication expectedAuthenticationObjectInContextHolder;
private boolean expectContextHolderContainSecureContext = false;
public MockFilterChain(
boolean expectContextHolderContainSecureContext,
Authentication expectedAuthenticationObjectInContextHolder) {
if ((expectedAuthenticationObjectInContextHolder != null)
&& !expectContextHolderContainSecureContext) {
throw new IllegalArgumentException(
"If an Authentication object is expected, the ContextHolder should contain a SecureContext");
}
this.expectContextHolderContainSecureContext = expectContextHolderContainSecureContext;
this.expectedAuthenticationObjectInContextHolder = expectedAuthenticationObjectInContextHolder;
}
private MockFilterChain() {
super();
}
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
if (expectContextHolderContainSecureContext) {
Context context = ContextHolder.getContext();
if (!(context instanceof SecureContext)) {
fail("ContextHolder should have contained SecureContext");
}
} else {
if (ContextHolder.getContext() != null) {
fail("ContextHolder should have been null but wasn't");
}
}
}
}
private class MockSecureContextImpl extends SecureContextImpl {
private String info;
public MockSecureContextImpl(String info) {
this.info = info;
}
private MockSecureContextImpl() {
super();
}
public String getInfo() {
return this.info;
}
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -26,8 +26,10 @@ import net.sf.acegisecurity.MockAuthenticationManager;
import net.sf.acegisecurity.MockFilterConfig; import net.sf.acegisecurity.MockFilterConfig;
import net.sf.acegisecurity.MockHttpServletRequest; import net.sf.acegisecurity.MockHttpServletRequest;
import net.sf.acegisecurity.MockHttpServletResponse; import net.sf.acegisecurity.MockHttpServletResponse;
import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.context.security.SecureContextUtils;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter;
import java.io.IOException; import java.io.IOException;
@ -59,10 +61,6 @@ public class AbstractProcessingFilterTests extends TestCase {
//~ Methods ================================================================ //~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
public static void main(String[] args) { public static void main(String[] args) {
junit.textui.TestRunner.run(AbstractProcessingFilterTests.class); junit.textui.TestRunner.run(AbstractProcessingFilterTests.class);
} }
@ -117,7 +115,7 @@ public class AbstractProcessingFilterTests extends TestCase {
executeFilterInContainerSimulator(config, filter, request, response, executeFilterInContainerSimulator(config, filter, request, response,
chain); chain);
assertEquals("/myApp/failed.jsp", response.getRedirect()); assertEquals("/myApp/failed.jsp", response.getRedirect());
assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) == null); assertNull(SecureContextUtils.getSecureContext().getAuthentication());
} }
public void testFilterProcessesUrlVariationsRespected() public void testFilterProcessesUrlVariationsRespected()
@ -144,10 +142,10 @@ public class AbstractProcessingFilterTests extends TestCase {
executeFilterInContainerSimulator(config, filter, request, response, executeFilterInContainerSimulator(config, filter, request, response,
chain); chain);
assertEquals("/logged_in.jsp", response.getRedirect()); assertEquals("/logged_in.jsp", response.getRedirect());
assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) != null); assertNotNull(SecureContextUtils.getSecureContext().getAuthentication());
assertEquals("test", assertEquals("test",
((Authentication) request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY)).getPrincipal() SecureContextUtils.getSecureContext().getAuthentication()
.toString()); .getPrincipal().toString());
} }
public void testGettersSetters() { public void testGettersSetters() {
@ -233,10 +231,10 @@ public class AbstractProcessingFilterTests extends TestCase {
executeFilterInContainerSimulator(config, filter, request, response, executeFilterInContainerSimulator(config, filter, request, response,
chain); chain);
assertEquals("/logged_in.jsp", response.getRedirect()); assertEquals("/logged_in.jsp", response.getRedirect());
assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) != null); assertNotNull(SecureContextUtils.getSecureContext().getAuthentication());
assertEquals("test", assertEquals("test",
((Authentication) request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY)).getPrincipal() SecureContextUtils.getSecureContext().getAuthentication()
.toString()); .getPrincipal().toString());
} }
public void testStartupDetectsInvalidAuthenticationFailureUrl() public void testStartupDetectsInvalidAuthenticationFailureUrl()
@ -327,10 +325,10 @@ public class AbstractProcessingFilterTests extends TestCase {
executeFilterInContainerSimulator(config, filter, request, response, executeFilterInContainerSimulator(config, filter, request, response,
chain); chain);
assertEquals("/logged_in.jsp", response.getRedirect()); assertEquals("/logged_in.jsp", response.getRedirect());
assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) != null); assertNotNull(SecureContextUtils.getSecureContext().getAuthentication());
assertEquals("test", assertEquals("test",
((Authentication) request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY)).getPrincipal() SecureContextUtils.getSecureContext().getAuthentication()
.toString()); .getPrincipal().toString());
// Now try again but this time have filter deny access // Now try again but this time have filter deny access
// Setup our HTTP request // Setup our HTTP request
@ -346,7 +344,7 @@ public class AbstractProcessingFilterTests extends TestCase {
// Test // Test
executeFilterInContainerSimulator(config, filter, request, response, executeFilterInContainerSimulator(config, filter, request, response,
chain); chain);
assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) == null); assertNull(SecureContextUtils.getSecureContext().getAuthentication());
} }
public void testSuccessfulAuthenticationButWithAlwaysUseDefaultTargetUrlCausesRedirectToDefaultTargetUrl() public void testSuccessfulAuthenticationButWithAlwaysUseDefaultTargetUrlCausesRedirectToDefaultTargetUrl()
@ -377,7 +375,7 @@ public class AbstractProcessingFilterTests extends TestCase {
executeFilterInContainerSimulator(config, filter, request, response, executeFilterInContainerSimulator(config, filter, request, response,
chain); chain);
assertEquals("/foobar", response.getRedirect()); assertEquals("/foobar", response.getRedirect());
assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) != null); assertNotNull(SecureContextUtils.getSecureContext().getAuthentication());
} }
public void testSuccessfulAuthenticationCausesRedirectToSessionSpecifiedUrl() public void testSuccessfulAuthenticationCausesRedirectToSessionSpecifiedUrl()
@ -404,7 +402,17 @@ public class AbstractProcessingFilterTests extends TestCase {
executeFilterInContainerSimulator(config, filter, request, response, executeFilterInContainerSimulator(config, filter, request, response,
chain); chain);
assertEquals("/my-destination", response.getRedirect()); assertEquals("/my-destination", response.getRedirect());
assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) != null); assertNotNull(SecureContextUtils.getSecureContext().getAuthentication());
}
protected void setUp() throws Exception {
super.setUp();
ContextHolder.setContext(new SecureContextImpl());
}
protected void tearDown() throws Exception {
super.tearDown();
ContextHolder.setContext(null);
} }
private void executeFilterInContainerSimulator(FilterConfig filterConfig, private void executeFilterInContainerSimulator(FilterConfig filterConfig,

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,7 +17,6 @@ package net.sf.acegisecurity.ui.basicauth;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.MockAuthenticationEntryPoint; import net.sf.acegisecurity.MockAuthenticationEntryPoint;
import net.sf.acegisecurity.MockAuthenticationManager; import net.sf.acegisecurity.MockAuthenticationManager;
import net.sf.acegisecurity.MockFilterConfig; import net.sf.acegisecurity.MockFilterConfig;
@ -25,7 +24,9 @@ import net.sf.acegisecurity.MockHttpServletRequest;
import net.sf.acegisecurity.MockHttpServletResponse; import net.sf.acegisecurity.MockHttpServletResponse;
import net.sf.acegisecurity.MockHttpSession; import net.sf.acegisecurity.MockHttpSession;
import net.sf.acegisecurity.UserDetails; import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.context.security.SecureContextUtils;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
@ -64,10 +65,6 @@ public class BasicProcessingFilterTests extends TestCase {
//~ Methods ================================================================ //~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
public static void main(String[] args) { public static void main(String[] args) {
junit.textui.TestRunner.run(BasicProcessingFilterTests.class); junit.textui.TestRunner.run(BasicProcessingFilterTests.class);
} }
@ -125,7 +122,7 @@ public class BasicProcessingFilterTests extends TestCase {
executeFilterInContainerSimulator(config, filter, request, response, executeFilterInContainerSimulator(config, filter, request, response,
chain); chain);
assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) == null); assertNull(SecureContextUtils.getSecureContext().getAuthentication());
} }
public void testGettersSetters() { public void testGettersSetters() {
@ -167,7 +164,7 @@ public class BasicProcessingFilterTests extends TestCase {
executeFilterInContainerSimulator(config, filter, request, response, executeFilterInContainerSimulator(config, filter, request, response,
chain); chain);
assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) == null); assertNull(SecureContextUtils.getSecureContext().getAuthentication());
} }
public void testNormalOperation() throws Exception { public void testNormalOperation() throws Exception {
@ -198,10 +195,11 @@ public class BasicProcessingFilterTests extends TestCase {
executeFilterInContainerSimulator(config, filter, request, response, executeFilterInContainerSimulator(config, filter, request, response,
chain); chain);
assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) != null); assertNotNull(SecureContextUtils.getSecureContext().getAuthentication());
assertEquals("marissa", assertEquals("marissa",
((UserDetails) ((Authentication) request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY)) ((UserDetails) SecureContextUtils.getSecureContext()
.getPrincipal()).getUsername()); .getAuthentication().getPrincipal())
.getUsername());
} }
public void testOtherAuthorizationSchemeIsIgnored() public void testOtherAuthorizationSchemeIsIgnored()
@ -231,7 +229,7 @@ public class BasicProcessingFilterTests extends TestCase {
executeFilterInContainerSimulator(config, filter, request, response, executeFilterInContainerSimulator(config, filter, request, response,
chain); chain);
assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) == null); assertNull(SecureContextUtils.getSecureContext().getAuthentication());
} }
public void testStartupDetectsMissingAuthenticationEntryPoint() public void testStartupDetectsMissingAuthenticationEntryPoint()
@ -290,10 +288,11 @@ public class BasicProcessingFilterTests extends TestCase {
executeFilterInContainerSimulator(config, filter, request, response, executeFilterInContainerSimulator(config, filter, request, response,
chain); chain);
assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) != null); assertNotNull(SecureContextUtils.getSecureContext().getAuthentication());
assertEquals("marissa", assertEquals("marissa",
((UserDetails) ((Authentication) request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY)) ((UserDetails) SecureContextUtils.getSecureContext()
.getPrincipal()).getUsername()); .getAuthentication().getPrincipal())
.getUsername());
// NOW PERFORM FAILED AUTHENTICATION // NOW PERFORM FAILED AUTHENTICATION
// Setup our HTTP request // Setup our HTTP request
@ -313,7 +312,7 @@ public class BasicProcessingFilterTests extends TestCase {
executeFilterInContainerSimulator(config, filter, request, response, executeFilterInContainerSimulator(config, filter, request, response,
chain); chain);
assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) == null); assertNull(SecureContextUtils.getSecureContext().getAuthentication());
assertEquals(401, response.getError()); assertEquals(401, response.getError());
} }
@ -345,10 +344,20 @@ public class BasicProcessingFilterTests extends TestCase {
executeFilterInContainerSimulator(config, filter, request, response, executeFilterInContainerSimulator(config, filter, request, response,
chain); chain);
assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) == null); assertNull(SecureContextUtils.getSecureContext().getAuthentication());
assertEquals(401, response.getError()); assertEquals(401, response.getError());
} }
protected void setUp() throws Exception {
super.setUp();
ContextHolder.setContext(new SecureContextImpl());
}
protected void tearDown() throws Exception {
super.tearDown();
ContextHolder.setContext(null);
}
private void executeFilterInContainerSimulator(FilterConfig filterConfig, private void executeFilterInContainerSimulator(FilterConfig filterConfig,
Filter filter, ServletRequest request, ServletResponse response, Filter filter, ServletRequest request, ServletResponse response,
FilterChain filterChain) throws ServletException, IOException { FilterChain filterChain) throws ServletException, IOException {

View File

@ -1,199 +0,0 @@
/* Copyright 2004 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.acegisecurity.ui.webapp;
import junit.framework.TestCase;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.MockHttpServletRequest;
import net.sf.acegisecurity.MockHttpSession;
import net.sf.acegisecurity.adapters.PrincipalAcegiUserToken;
import java.util.List;
import java.util.Vector;
/**
* Tests {@link HttpSessionIntegrationFilter}.
*
* @author Ben Alex
* @version $Id$
*/
public class HttpSessionIntegrationFilterTests extends TestCase {
//~ Constructors ===========================================================
public HttpSessionIntegrationFilterTests() {
super();
}
public HttpSessionIntegrationFilterTests(String arg0) {
super(arg0);
}
//~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
public static void main(String[] args) {
junit.textui.TestRunner.run(HttpSessionIntegrationFilterTests.class);
}
public void testCommitFailSilentlyIfNullsProvided() {
HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter();
filter.commitToContainer(null, null);
assertTrue(true);
}
public void testCommitOperation() {
// Build an Authentication object we want returned
PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key",
"someone", "password",
new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")});
// Build a mock request
MockHttpSession session = new MockHttpSession();
MockHttpServletRequest request = new MockHttpServletRequest(null,
session);
// Try to commit
HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter();
filter.commitToContainer(request, principal);
// Check it committed the object
Object result = session.getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY);
assertEquals(principal, result);
}
public void testCommitOperationGracefullyIgnoredIfSessionIsNull() {
PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key",
"someone", "password",
new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")});
// Build a mock request
MockHttpSession session = null;
MockHttpServletRequest request = new MockHttpServletRequest(null,
session);
HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter();
filter.commitToContainer(request, principal);
assertTrue(true);
}
public void testCorrectOperation() {
// Build a mock session containing the authenticated user
PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key",
"someone", "password",
new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")});
MockHttpSession session = new MockHttpSession();
session.setAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY,
principal);
// Confirm filter can extract required credentials from session
HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter();
Object result = filter.extractFromContainer(new MockHttpServletRequest(
null, session));
if (!(result instanceof PrincipalAcegiUserToken)) {
fail("Should have returned PrincipalAcegiUserToken");
}
PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result;
assertEquals(principal, result);
}
public void testDetectsInvalidAdditionalAttributes() {
HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter();
List list = new Vector();
list.add(new Integer(4));
try {
filter.setAdditionalAttributes(list);
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertTrue(true);
}
}
public void testHandlesIfHttpRequestIsNullForSomeReason() {
HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter();
assertEquals(null, filter.extractFromContainer(null));
}
public void testHandlesIfHttpSessionIsNullForSomeReason() {
HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter();
assertEquals(null,
filter.extractFromContainer(new MockHttpServletRequest(null, null)));
}
public void testHandlesIfThereIsNoPrincipalInTheHttpSession() {
HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter();
assertEquals(null,
filter.extractFromContainer(
new MockHttpServletRequest(null, new MockHttpSession())));
}
public void testSettingEmptyListForAdditionalAttributesIsAcceptable() {
HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter();
filter.setAdditionalAttributes(new Vector());
assertTrue(filter.getAdditionalAttributes() != null);
}
public void testSettingNullForAdditionalAttributesIsAcceptable() {
HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter();
filter.setAdditionalAttributes(null);
assertNull(filter.getAdditionalAttributes());
}
public void testUpdatesAdditionalAttributes() {
// Build a mock session containing the authenticated user
PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key",
"someone", "password",
new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")});
MockHttpSession session = new MockHttpSession();
session.setAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY,
principal);
// Check our attributes are not presently set
assertNull(session.getAttribute("SOME_EXTRA_ATTRIBUTE_1"));
assertNull(session.getAttribute("SOME_EXTRA_ATTRIBUTE_2"));
// Generate filter
HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter();
List list = new Vector();
list.add("SOME_EXTRA_ATTRIBUTE_1");
list.add("SOME_EXTRA_ATTRIBUTE_2");
filter.setAdditionalAttributes(list);
// Confirm filter can extract required credentials from session
Object result = filter.extractFromContainer(new MockHttpServletRequest(
null, session));
if (!(result instanceof PrincipalAcegiUserToken)) {
fail("Should have returned PrincipalAcegiUserToken");
}
PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result;
assertEquals(principal, result);
// Now double-check it updated our earlier set additionalAttributes
assertEquals(principal, session.getAttribute("SOME_EXTRA_ATTRIBUTE_1"));
assertEquals(principal, session.getAttribute("SOME_EXTRA_ATTRIBUTE_2"));
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -13,12 +13,14 @@
* limitations under the License. * limitations under the License.
*/ */
package net.sf.acegisecurity.ui.wrapper; package net.sf.acegisecurity.wrapper;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.acegisecurity.MockFilterConfig; import net.sf.acegisecurity.MockFilterConfig;
import net.sf.acegisecurity.MockHttpServletRequest; import net.sf.acegisecurity.MockHttpServletRequest;
import net.sf.acegisecurity.wrapper.ContextHolderAwareRequestFilter;
import net.sf.acegisecurity.wrapper.ContextHolderAwareRequestWrapper;
import java.io.IOException; import java.io.IOException;

View File

@ -13,7 +13,7 @@
* limitations under the License. * limitations under the License.
*/ */
package net.sf.acegisecurity.ui.wrapper; package net.sf.acegisecurity.wrapper;
import junit.framework.TestCase; import junit.framework.TestCase;
@ -22,10 +22,11 @@ import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl; import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.MockHttpServletRequest; import net.sf.acegisecurity.MockHttpServletRequest;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.context.SecureContextImpl; import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.providers.TestingAuthenticationToken; import net.sf.acegisecurity.providers.TestingAuthenticationToken;
import net.sf.acegisecurity.providers.dao.User; import net.sf.acegisecurity.providers.dao.User;
import net.sf.acegisecurity.wrapper.ContextHolderAwareRequestWrapper;
/** /**

View File

@ -26,7 +26,7 @@
<subtitle>Reference Documentation</subtitle> <subtitle>Reference Documentation</subtitle>
<releaseinfo>0.7.0</releaseinfo> <releaseinfo>0.8.0</releaseinfo>
<authorgroup> <authorgroup>
<author> <author>
@ -399,6 +399,43 @@
custom request contexts implement the <literal>SecureContext</literal> custom request contexts implement the <literal>SecureContext</literal>
interface.</para> interface.</para>
</sect2> </sect2>
<sect2 id="security-contexts-storage">
<title>Context Storage</title>
<para>Central to Acegi Security's design is that the contents of the
<literal>ContextHolder</literal> (ie the <literal>Context</literal>)
can be stored between web requests. This is so that a successfully
authenticated principal can be identified on subsequent requests
through the <literal>Authentication</literal> stored inside a
<literal>SecureContext</literal> implementation. The
<literal>HttpSessionContextIntegrationFilter</literal> exists to
automatically copy the contents of a well-defined
<literal>HttpSession</literal> attribute into the
<literal>ContextHolder</literal>, then at the end of each request,
copy the <literal>ContextHolder</literal> contents back into the
<literal>HttpSession</literal> ready for next request.</para>
<para>It is essential - and an extremely common error of end users -
that <literal>HttpSessionContextIntegrationFilter</literal> appears
before any other Acegi Security filter. This is because other Acegi
Security filters (along with all Acegi Security classes) expect the
<literal>ContextHolder</literal> to contain a valid
<literal>SecureContext</literal> by the time they are called. Acegi
Security filters also expect to be able to modify the
<literal>ContextHolder</literal> contents as they see fit, and
something else will store those between requests if necessary. This is
why <literal>HttpSessionContextIntegrationFilter</literal> must be the
first filter used.</para>
<para>The <literal>HttpSessionContextIntegrationFilter</literal> has
been designed to store all types of <literal>Context</literal> objects
- not merely Acegi Security related contexts. This means, for example,
that you can extend <literal>SecureContextImpl</literal> to store a
locale or some other parameter, and
<literal>HttpSessionContextIntegrationFilter</literal> will
automatically manage it between web requests.</para>
</sect2>
</sect1> </sect1>
<sect1 id="security-interception"> <sect1 id="security-interception">
@ -2264,44 +2301,42 @@ public boolean supports(Class clazz);</programlisting></para>
classes "authentication mechanisms".</para> classes "authentication mechanisms".</para>
<para>The <literal>net.sf.acegisecurity.ui</literal> package provides <para>The <literal>net.sf.acegisecurity.ui</literal> package provides
authentication mechanisms for web applications. There are two major what we call "authentication processing mechanisms". An authentication
steps in doing this:</para> processing mechanism is solely concerned with received an
authentication request from the principal, testing if it seems valid,
and if so, placing the authentication request token onto the
ContextHolder. Of course, if the authentication request is invalid,
the authentication processing mechanism is responsible for informing
the principal in whatever way is appropriate to the protocol.</para>
<para><itemizedlist spacing="compact"> <para>Recall the HttpSessionContextIntegrationFilter (discussed in the
<listitem> context section) is responsible for storing the ContextHolder contents
<para>Actually authenticate the user and place the resulting between invocations. This means no authentication processing mechanism
<literal>Authentication</literal> object in a "well-known need ever interact directly with HttpSession. Indeed
location".</para> HttpSessionContextIntegrationFilter has been designed to minimise the
</listitem> unnecessary creation of HttpSessions, as might occur when using Basic
authentication for example.</para>
<listitem> <para>There are several authentication processing mechanisms included
<para>Extract the <literal>Authentication</literal> object from with Acegi Security, which will be briefly discussed in this chapter.
the "well-known location" and place in into the The most popular (and almost always recommended) approach is HTTP Form
<literal>ContextHolder</literal> for the duration of the secure Authentication, which uses a login form to authenticate the user.
object invocation.</para> Another approach (commonly use with web services) is HTTP Basic
</listitem> Authentication, which allows clients to use HTTP headers to present
</itemizedlist></para> authentication information to the Acegi Security System for Spring.
Alternatively, you can also use Yale Central Authentication Service
<para>There are several alternatives are available for the first step, (CAS) for enterprise-wide single sign on. The final (and generally
which will be briefly discussed in this chapter. The most popular (and unrecommended) approach is via Container Adapters, which allow
almost always recommended) approach is HTTP Session Authentication, supported web containers to perform the authentication themselves.
which uses the <literal>HttpSession</literal> object and filters to HTTP Form Authentication and Basic Authentication is discussed below,
authenticate the user. Another approach (commonly use with web whilst CAS and Container Adapters are discussed in separate sections
services) is HTTP Basic Authentication, which allows clients to use of this document.</para>
HTTP headers to present authentication information to the Acegi
Security System for Spring. Alternatively, you can also use Yale
Central Authentication Service (CAS) for enterprise-wide single sign
on. The final (generally unrecommended) approach is via Container
Adapters, which allow supported web containers to perform the
authentication themselves. HTTP Session and Basic Authentication is
discussed below, whilst CAS and Container Adapters are discussed in
separate sections of this document.</para>
</sect2> </sect2>
<sect2 id="security-ui-http-session"> <sect2 id="security-ui-http-form">
<title>HTTP Session Authentication</title> <title>HTTP Form Authentication</title>
<para>HTTP Session Authentication involves using the <para>HTTP Form Authentication involves using the
<literal>AuthenticationProcessingFilter</literal> to process a login <literal>AuthenticationProcessingFilter</literal> to process a login
form. The login form simply contains <literal>j_username</literal> and form. The login form simply contains <literal>j_username</literal> and
<literal>j_password</literal> input fields, and posts to a URL that is <literal>j_password</literal> input fields, and posts to a URL that is
@ -2346,12 +2381,9 @@ public boolean supports(Class clazz);</programlisting></para>
<para>If authentication is successful, the resulting <para>If authentication is successful, the resulting
<literal>Authentication</literal> object will be placed into the <literal>Authentication</literal> object will be placed into the
<literal>HttpSession</literal> attribute indicated by <literal>ContextHolder</literal>.</para>
<literal>HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY</literal>.
This becomes the "well-known location" from which the
<literal>Authentication</literal> object is later extracted.</para>
<para>Once the <literal>HttpSession</literal> has been updated, the <para>Once the <literal>ContextHolder</literal> has been updated, the
browser will need to be redirected to the target URL. The target URL browser will need to be redirected to the target URL. The target URL
is usually indicated by the <literal>HttpSession</literal> attribute is usually indicated by the <literal>HttpSession</literal> attribute
specified by specified by
@ -2365,8 +2397,8 @@ public boolean supports(Class clazz);</programlisting></para>
<literal>defaultTargetUrl</literal> property.</para> <literal>defaultTargetUrl</literal> property.</para>
<para>Because this authentication approach is fully contained within a <para>Because this authentication approach is fully contained within a
single web application, HTTP Session Authentication is recommended to single web application, HTTP Form Authentication is recommended to be
be used instead of Container Adapters.</para> used instead of Container Adapters.</para>
</sect2> </sect2>
<sect2 id="security-ui-http-basic"> <sect2 id="security-ui-http-basic">
@ -2421,10 +2453,7 @@ public boolean supports(Class clazz);</programlisting></para>
401 response with a suitable header to retry HTTP Basic 401 response with a suitable header to retry HTTP Basic
authentication. If authentication is successful, the resulting authentication. If authentication is successful, the resulting
<literal>Authentication</literal> object will be placed into the <literal>Authentication</literal> object will be placed into the
<literal>HttpSession</literal> attribute indicated by <literal>ContextHolder</literal>.</para>
<literal>HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY</literal>.
This becomes the "well-known location" from which the
<literal>Authentication</literal> object is later extracted.</para>
<para>If the authentication event was successful, or authentication <para>If the authentication event was successful, or authentication
was not attempted because the HTTP header did not contain a supported was not attempted because the HTTP header did not contain a supported
@ -2434,94 +2463,32 @@ public boolean supports(Class clazz);</programlisting></para>
as discussed in the previous paragraph.</para> as discussed in the previous paragraph.</para>
<para>HTTP Basic Authentication is recommended to be used instead of <para>HTTP Basic Authentication is recommended to be used instead of
Container Adapters. It can be used in conjunction with HTTP Session Container Adapters. It can be used in conjunction with HTTP Form
Authentication, as demonstrated in the Contacts sample application. Authentication, as demonstrated in the Contacts sample application.
You can also use it instead of HTTP Session Authentication if you You can also use it instead of HTTP Form Authentication if you
wish.</para> wish.</para>
</sect2> </sect2>
<sect2 id="security-ui-well-known"> <sect2 id="security-ui-well-known">
<title>Well-Known Location Integration</title> <title>Well-Known Locations</title>
<para>Once a web application has used either HTTP Session <para>Prior to release 0.8.0, Acegi Security referred to "well-known
Authentication, HTTP Basic Authentication, or a Container Adapter, an locations" in discussions about storing the
<literal>Authentication</literal> object will exist in a well-known <literal>Authentication</literal>. This approach did not explicitly
location. The final step in automatically integrating the user separate the function of <literal>HttpSession</literal> storage of
interface with the backend security interceptor is to extract this <literal>ContextHolder</literal> contents from the processing of
<literal>Authentication</literal> object from the well-known location authentication requests received through various protocols. In
and place it into a <literal>SecureContext</literal> in the addition, the previous approach did not facilitate storage of
<literal>ContextHolder</literal>.</para> non-<literal>Authentication</literal> objects between requests, which
was limiting usefulness of the <literal>ContextHolder</literal> system
<para>The <literal>AbstractIntegrationFilter</literal> and its to member of the community. For these reasons, the notion of
subclasses provide this well-known location integration. These classes well-known locations was abandoned, the
are standard filters, and at the start of each request they will <literal>HttpSessionContextIntegrationFilter</literal> was
attempt to extract the <literal>Authentication</literal> object from a established, and the purpose of authentication processing mechanisms
well-known location. The <literal>Authentication</literal> object will was explicitly defined and limited to interaction with the
then be added to a <literal>SecureContext</literal>, the <literal>ContextHolder</literal> only. There is no need to refer to
<literal>SecureContext</literal> associated with the well-known locations any more and we hope this clearer separation of
<literal>ContextHolder</literal> for the duration of the request, and responsibilities enhances understanding of the project.</para>
the <literal>ContextHolder</literal> be cleared when the request is
finished. Four concrete subclasses of
<literal>AbstractIntegrationFilter</literal> are provided with the
Acegi Security System for Spring:</para>
<para><itemizedlist>
<listitem>
<para><literal>HttpSessionIntegrationFilter</literal> is used
with HTTP Session Authentication, HTTP Basic Authentication, or
any other approach that populates the
<literal>HttpSession</literal> accordingly. It extracts the
<literal>Authentication</literal> object from the
<literal>HttpSession</literal> attribute indicated by
<literal>HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY</literal>.</para>
</listitem>
<listitem>
<para><literal>HttpRequestIntegrationFilter</literal> is used
with Catalina, Jetty and Resin Container Adapters. It extracts
the authentication information from
<literal>HttpServletRequest.getUserPrincipal()</literal>.</para>
</listitem>
<listitem>
<para><literal>JbossIntegrationFilter</literal> is used with the
JBoss Container Adapter. It extracts the authentication from
<literal>java:comp/env/security/subject</literal>.</para>
</listitem>
</itemizedlist></para>
<para>To define the <literal>HttpSessionIntegrationFilter</literal>
(recommended), simply add the following to your web.xml:</para>
<para><programlisting>&lt;filter&gt;
&lt;filter-name&gt;Acegi Security System for Spring HttpSession Integration Filter&lt;/filter-name&gt;
&lt;filter-class&gt;net.sf.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt;
&lt;init-param&gt;
&lt;param-name&gt;targetClass&lt;/param-name&gt;
&lt;param-value&gt;net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;/filter&gt;
&lt;filter-mapping&gt;
&lt;filter-name&gt;Acegi Security System for Spring HttpSession Integration Filter&lt;/filter-name&gt;
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;</programlisting></para>
<para>You will also need to add the following line to your application
context:</para>
<para><programlisting>&lt;bean id="httpSessionIntegrationFilter" class="net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter" /&gt;</programlisting></para>
<para>Once in the <literal>ContextHolder</literal>, the standard Acegi
Security System for Spring classes can be used. Because
<literal>ContextHolder</literal> is a standard object which is
populated using a filter at the container level, JSPs and Servlets do
not need to use Spring's MVC packages. This enables those applications
that use other MVC frameworks to still leverage Spring's other
capabilities, with full authentication and authorization support. The
<literal>debug.jsp</literal> page provided with the sample application
demonstrates accessing the <literal>ContextHolder</literal>
independent of Spring's MVC packages.</para>
</sect2> </sect2>
</sect1> </sect1>
@ -2531,13 +2498,14 @@ public boolean supports(Class clazz);</programlisting></para>
<sect2 id="security-container-adapters-overview"> <sect2 id="security-container-adapters-overview">
<title>Overview</title> <title>Overview</title>
<para>Early versions of the Acegi Security System for Spring <para>Very early versions of the Acegi Security System for Spring
exclusively used Container Adapters for interfacing authentication exclusively used Container Adapters for interfacing authentication
with end users. Whilst this worked well, it required considerable time with end users. Whilst this worked well, it required considerable time
to support multiple container versions and the configuration itself to support multiple container versions and the configuration itself
was relatively time-consuming for developers. For this reason the HTTP was relatively time-consuming for developers. For this reason the HTTP
Session Authentication and HTTP Basic Authentication approaches were Form Authentication and HTTP Basic Authentication approaches were
developed, and are today recommended for most applications.</para> developed, and are today recommended for almost all
applications.</para>
<para>Container Adapters enable the Acegi Security System for Spring <para>Container Adapters enable the Acegi Security System for Spring
to integrate directly with the containers used to host end user to integrate directly with the containers used to host end user
@ -2546,7 +2514,10 @@ public boolean supports(Class clazz);</programlisting></para>
containers (such as <literal>isUserInRole()</literal> and form-based containers (such as <literal>isUserInRole()</literal> and form-based
or basic authentication), whilst benefiting from the enhanced security or basic authentication), whilst benefiting from the enhanced security
interception capabilities provided by the Acegi Security System for interception capabilities provided by the Acegi Security System for
Spring.</para> Spring (it should be noted that Acegi Security also offers
<literal>ContextHolderAwareRequestWrapper</literal> to deliver
<literal>isUserInRole()</literal> and similar Servlet Specification
compatibility methods).</para>
<para>The integration between a container and the Acegi Security <para>The integration between a container and the Acegi Security
System for Spring is achieved through an adapter. The adapter provides System for Spring is achieved through an adapter. The adapter provides
@ -4208,8 +4179,8 @@ INSERT INTO acl_permission VALUES (null, 6, 'scott', 1);</programlisting></para>
&lt;value&gt; &lt;value&gt;
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT PATTERN_TYPE_APACHE_ANT
/webServices/**=basicProcessingFilter,httpSessionIntegrationFilter,securityEnforcementFilter /webServices/**=httpSessionContextIntegrationFilterWithASCFalse,basicProcessingFilter,securityEnforcementFilter
/**=authenticationProcessingFilter,httpSessionIntegrationFilter,securityEnforcementFilter /**=httpSessionContextIntegrationFilterWithASCTrue,authenticationProcessingFilter,securityEnforcementFilter
&lt;/value&gt; &lt;/value&gt;
&lt;/property&gt; &lt;/property&gt;
&lt;/bean&gt;</programlisting></para> &lt;/bean&gt;</programlisting></para>
@ -4228,8 +4199,8 @@ INSERT INTO acl_permission VALUES (null, 6, 'scott', 1);</programlisting></para>
<para>As you can see, <literal>FitlerChainProxy</literal> requires the <para>As you can see, <literal>FitlerChainProxy</literal> requires the
duplication of filter names for different request patterns (in the duplication of filter names for different request patterns (in the
above example, <literal>httpSessionIntegrationFilter</literal> and above example, <literal>httpSessionContextIntegrationFilter</literal>
<literal>securityEnforcementFilter</literal> are duplicated). This and <literal>securityEnforcementFilter</literal> are duplicated). This
design decision was made to enable <literal>FilterChainProxy</literal> design decision was made to enable <literal>FilterChainProxy</literal>
to specify different <literal>Filter</literal> invocation orders for to specify different <literal>Filter</literal> invocation orders for
different URI patterns, and also to improve both the expressiveness different URI patterns, and also to improve both the expressiveness
@ -4238,6 +4209,20 @@ INSERT INTO acl_permission VALUES (null, 6, 'scott', 1);</programlisting></para>
and clarity of which <literal>Filter</literal>s should be and clarity of which <literal>Filter</literal>s should be
invoked.</para> invoked.</para>
<para>You may have noticed we have declared two
<literal>HttpSessionContextIntegrationFilter</literal>s in the filter
chain (<literal>ASC</literal> is short for
<literal>allowSessionCreation</literal>, a property of
<literal>HttpSessionContextIntegrationFilter</literal>). As web
services will never present a <literal>jsessionid</literal> on future
requests, creating <literal>HttpSession</literal>s for such user
agents would be wasteful. If you had a high-volume application which
required maximum scalability, we recommend you use the approach shown
above. For smaller applications, using a single
<literal>HttpSessionContextIntegrationFilter</literal> (with its
default <literal>allowSessionCreation</literal> as
<literal>true</literal>) would likely be sufficient.</para>
<para>In relation to lifecycle issues, the <para>In relation to lifecycle issues, the
<literal>FilterChainProxy</literal> will always delegate <literal>FilterChainProxy</literal> will always delegate
<literal>init(FilterConfig)</literal> and <literal>destroy()</literal> <literal>init(FilterConfig)</literal> and <literal>destroy()</literal>
@ -4259,7 +4244,7 @@ INSERT INTO acl_permission VALUES (null, 6, 'scott', 1);</programlisting></para>
<title>Filter Ordering</title> <title>Filter Ordering</title>
<para>The order that filters are defined in <literal>web.xml</literal> <para>The order that filters are defined in <literal>web.xml</literal>
is important.</para> is important. NB: THE FILTER ORDER CHANGED FROM VERSION 0.8.0.</para>
<para>Irrespective of which filters you are actually using, the order <para>Irrespective of which filters you are actually using, the order
of the <literal>&lt;filter-mapping&gt;</literal>s should be as of the <literal>&lt;filter-mapping&gt;</literal>s should be as
@ -4267,33 +4252,41 @@ INSERT INTO acl_permission VALUES (null, 6, 'scott', 1);</programlisting></para>
<orderedlist> <orderedlist>
<listitem> <listitem>
<para>Acegi Channel Processing Filter <para><literal>ChannelProcessingFilter</literal>, because it might
(<literal>ChannelProcessingFilter</literal>)</para> need to redirect to a different protocol</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Acegi Authentication Processing Filter <para><literal>HttpSessionContextIntegrationFilter</literal>, so a
(<literal>AuthenticationProcessingFilter</literal>)</para> <literal>Context</literal> can be setup in the
<literal>ContextHolder</literal> at the beginning of a web
request, and any changes to the Context can be copied to the
<literal>HttpSession</literal> when the web request ends (ready
for use with the next web request)</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Acegi CAS Processing Filter <para>Authentication processing mechanisms -
(<literal>CasProcessingFilter</literal>)</para> <literal>AuthenticationProcessingFilter</literal>,
<literal>CasProcessingFilter</literal>,
<literal>BasicProcessingFilter, HttpRequestIntegrationFilter,
JbossIntegrationFilter</literal> etc - so that the
<literal>ContextHolder</literal> can be modified to contain a
valid <literal>Authentication</literal> request token</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Acegi HTTP BASIC Authorization Filter <para>The <literal>ContextHolderAwareRequestFilter</literal>, if
(<literal>BasicProcessingFilter</literal>)</para> you are using it to install an Acegi Security aware
<literal>HttpServletRequestWrapper</literal> into your servlet
container</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Acegi Security System for Spring HTTP Session Integration <para><literal>SecurityEnforcementFilter</literal>, to protect web
Filter (<literal>HttpSessionIntegrationFilter</literal>)</para> URIs and catch any Acegi Security exceptions so that an
</listitem> appropriate <literal>AuthenticationEntryPoint</literal> can be
launched</para>
<listitem>
<para>Acegi HTTP Request Security Filter
(<literal>SecurityEnforcementFilter</literal>)</para>
</listitem> </listitem>
</orderedlist> </orderedlist>
@ -4353,7 +4346,7 @@ INSERT INTO acl_permission VALUES (null, 6, 'scott', 1);</programlisting></para>
<blockquote> <blockquote>
<para>Context on ContextHolder is of type: <para>Context on ContextHolder is of type:
net.sf.acegisecurity.context.SecureContextImpl</para> net.sf.acegisecurity.context.secure.SecureContextImpl</para>
<para>The Context implements SecureContext.</para> <para>The Context implements SecureContext.</para>

View File

@ -45,6 +45,7 @@
<action dev="benalex" type="add">Additional debug-level logging</action> <action dev="benalex" type="add">Additional debug-level logging</action>
<action dev="benalex" type="add">AuthenticationProcessingFilter now provides hook for extra credentials (eg postcodes)</action> <action dev="benalex" type="add">AuthenticationProcessingFilter now provides hook for extra credentials (eg postcodes)</action>
<action dev="benalex" type="add">New WebAuthenticationDetails class now used by processing filters for Authentication.setDetails()</action> <action dev="benalex" type="add">New WebAuthenticationDetails class now used by processing filters for Authentication.setDetails()</action>
<action dev="benalex" type="update">Significantly refactor "well-known location model" to authentication processing mechanism and HttpSessionContextIntegrationFilter model</action>
</release> </release>
<release version="0.7.0" date="2005-01-16"> <release version="0.7.0" date="2005-01-16">
<action dev="carlossg" type="add">Major CVS repository restructure to support Maven and eliminate libraries</action> <action dev="carlossg" type="add">Major CVS repository restructure to support Maven and eliminate libraries</action>

View File

@ -0,0 +1,38 @@
<html>
<head>
<title>Acegi Security - Upgrading from version 0.7.0 to 0.8.0</title>
</head>
<body>
<h1>Upgrading from 0.7.0 to 0.8.0</h1>
<p>
The following should help most casual users of the project update their
applications:
<ul>
<li>HttpSessionIntegrationFilter has been removed. Use net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter instead.
Note you will need to set the mandatory "context" property to something like "net.sf.acegisecurity.context.security.SecureContextImpl".
It's not the default because we want no dependencies between the context package and the rest of Acegi Security.<br><br></li>
<li>Filter ordering has changed. See the reference guide for confirmation of the correct ordering. Basically you should have
HttpSessionContextIntegrationFilter appear before any of your authentication mechanisms.<br><br></li>
<li>IoC container hosted filter chains can now be used instead of lengthy web.xml declarations. See the reference guide or the
Contacts Sample for further information.<br><br></li>
<li>Certain classes have been moved to new packages: ContextHolderAwareRequestWrapper (and its filter),
AuthenticationSimpleHttpInvokerRequestExecutor, ContextPropagatingRemoteInvocation,
SecureContext (and its implementation). These classes were moved as part of refactorings aimed at
improving the simplicity of the project's design.<br><br></li>
<li>The JaasAuthenticationCallbackHandler interface has had it's setAuthentication method removed. The handle method now takes both the Callback and Authentication objects as arguments.<br><br></li>
<li>Added AuthenticationException to the AutenticationEntryPoint.commence method signature.<br><br></li>
<li>Added AccessDeniedException to the SecurityEncorcementFilter.sendAccessDeniedError method signature.<br><br></li>
</ul>
</body>
</html>

View File

@ -1,22 +0,0 @@
<html>
<head>
<title>Acegi Security - Upgrading from version 0.7.0 to 1.0.0</title>
</head>
<body>
<h1>Upgrading from 0.7.0 to 1.0.0</h1>
<p>
The following should help most casual users of the project update their
applications:
<ul>
<li>The JaasAuthenticationCallbackHandler interface has had it's setAuthentication method removed.
The handle method now takes both the Callback and Authentication objects as arguments.</li>
<li>Added AuthenticationException to the AutenticationEntryPoint.commence method signature.</li>
<li>Added AccessDeniedException to the SecurityEncorcementFilter.sendAccessDeniedError method signature.</li>
</ul>
</body>
</html>

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,7 +19,7 @@ import net.sf.acegisecurity.AccessDeniedException;
import net.sf.acegisecurity.GrantedAuthority; import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl; import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContextImpl; import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.providers.TestingAuthenticationToken; import net.sf.acegisecurity.providers.TestingAuthenticationToken;
import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -21,7 +21,7 @@ import net.sf.acegisecurity.AccessDeniedException;
import net.sf.acegisecurity.GrantedAuthority; import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl; import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContextImpl; import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.providers.TestingAuthenticationToken; import net.sf.acegisecurity.providers.TestingAuthenticationToken;
import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,8 +17,8 @@ package sample.contact;
import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.context.SecureContextImpl; import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.ListableBeanFactory;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited /* Copyright 2004, 2005 Acegi Technology Pty Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,7 +20,7 @@ import net.sf.acegisecurity.acl.basic.BasicAclExtendedDao;
import net.sf.acegisecurity.acl.basic.NamedEntityObjectIdentity; import net.sf.acegisecurity.acl.basic.NamedEntityObjectIdentity;
import net.sf.acegisecurity.acl.basic.SimpleAclEntry; import net.sf.acegisecurity.acl.basic.SimpleAclEntry;
import net.sf.acegisecurity.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext; import net.sf.acegisecurity.context.security.SecureContext;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;

View File

@ -21,7 +21,7 @@
<value> <value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT PATTERN_TYPE_APACHE_ANT
/**=httpRequestIntegrationFilter /**=httpSessionContextIntegrationFilter,httpRequestIntegrationFilter
</value> </value>
</property> </property>
</bean> </bean>
@ -46,6 +46,10 @@
<bean id="httpRequestIntegrationFilter" class="net.sf.acegisecurity.adapters.HttpRequestIntegrationFilter"/> <bean id="httpRequestIntegrationFilter" class="net.sf.acegisecurity.adapters.HttpRequestIntegrationFilter"/>
<bean id="httpSessionContextIntegrationFilter" class="net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter">
<property name="context"><value>net.sf.acegisecurity.context.security.SecureContextImpl</value></property>
</bean>
<!-- ===================== HTTP CHANNEL REQUIREMENTS ==================== --> <!-- ===================== HTTP CHANNEL REQUIREMENTS ==================== -->
<!-- Implement by servlet specification --> <!-- Implement by servlet specification -->

View File

@ -19,7 +19,7 @@
<value> <value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT PATTERN_TYPE_APACHE_ANT
/**=channelProcessingFilter,casProcessingFilter,basicProcessingFilter,httpSessionIntegrationFilter,securityEnforcementFilter /**=channelProcessingFilter,httpSessionContextIntegrationFilter,casProcessingFilter,basicProcessingFilter,securityEnforcementFilter
</value> </value>
</property> </property>
</bean> </bean>
@ -47,7 +47,9 @@
<property name="realmName"><value>Contacts Realm</value></property> <property name="realmName"><value>Contacts Realm</value></property>
</bean> </bean>
<bean id="httpSessionIntegrationFilter" class="net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter"/> <bean id="httpSessionContextIntegrationFilter" class="net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter">
<property name="context"><value>net.sf.acegisecurity.context.security.SecureContextImpl</value></property>
</bean>
<bean id="casAuthenticationProvider" class="net.sf.acegisecurity.providers.cas.CasAuthenticationProvider"> <bean id="casAuthenticationProvider" class="net.sf.acegisecurity.providers.cas.CasAuthenticationProvider">
<property name="casAuthoritiesPopulator"><ref local="casAuthoritiesPopulator"/></property> <property name="casAuthoritiesPopulator"><ref local="casAuthoritiesPopulator"/></property>

View File

@ -1,6 +1,6 @@
<%@ page import="net.sf.acegisecurity.context.Context" %> <%@ page import="net.sf.acegisecurity.context.Context" %>
<%@ page import="net.sf.acegisecurity.context.ContextHolder" %> <%@ page import="net.sf.acegisecurity.context.ContextHolder" %>
<%@ page import="net.sf.acegisecurity.context.SecureContext" %> <%@ page import="net.sf.acegisecurity.context.security.SecureContext" %>
<%@ page import="net.sf.acegisecurity.Authentication" %> <%@ page import="net.sf.acegisecurity.Authentication" %>
<%@ page import="net.sf.acegisecurity.GrantedAuthority" %> <%@ page import="net.sf.acegisecurity.GrantedAuthority" %>
<%@ page import="net.sf.acegisecurity.adapters.AuthByAdapter" %> <%@ page import="net.sf.acegisecurity.adapters.AuthByAdapter" %>

View File

@ -15,13 +15,13 @@
<!-- ======================== FILTER CHAIN ======================= --> <!-- ======================== FILTER CHAIN ======================= -->
<!-- if you wish to use channel security, add "channelProcessingFilter," in front <!-- if you wish to use channel security, add "channelProcessingFilter," in front
of "authenticationProcessingFilter" in the list below --> of "httpSessionContextIntegrationFilter" in the list below -->
<bean id="filterChainProxy" class="net.sf.acegisecurity.util.FilterChainProxy"> <bean id="filterChainProxy" class="net.sf.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource"> <property name="filterInvocationDefinitionSource">
<value> <value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT PATTERN_TYPE_APACHE_ANT
/**=authenticationProcessingFilter,basicProcessingFilter,httpSessionIntegrationFilter,securityEnforcementFilter /**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,basicProcessingFilter,securityEnforcementFilter
</value> </value>
</property> </property>
</bean> </bean>
@ -75,7 +75,9 @@
<property name="realmName"><value>Contacts Realm</value></property> <property name="realmName"><value>Contacts Realm</value></property>
</bean> </bean>
<bean id="httpSessionIntegrationFilter" class="net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter"/> <bean id="httpSessionContextIntegrationFilter" class="net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter">
<property name="context"><value>net.sf.acegisecurity.context.security.SecureContextImpl</value></property>
</bean>
<!-- ===================== HTTP CHANNEL REQUIREMENTS ==================== --> <!-- ===================== HTTP CHANNEL REQUIREMENTS ==================== -->