63 changed files with 1334 additions and 1347 deletions
@ -0,0 +1,289 @@
@@ -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 {} |
||||
} |
||||
@ -0,0 +1,45 @@
@@ -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(); |
||||
} |
||||
} |
||||
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
<html> |
||||
<body> |
||||
Provides a <code>Context</code> that is designed to be compatible with |
||||
Acegi Security. |
||||
</body> |
||||
</html> |
||||
|
||||
@ -1,232 +0,0 @@
@@ -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 {} |
||||
} |
||||
@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
|
||||
<html> |
||||
<body> |
||||
Interfaces the system with various end-user authentication approaches, such |
||||
as container adapters and web applications. |
||||
Authentication processing mechanisms, which respond to the submission of authentication |
||||
credentials using various protocols (eg BASIC, CAS, form login etc). |
||||
</body> |
||||
</html> |
||||
|
||||
@ -1,158 +0,0 @@
@@ -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!"); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,245 @@
@@ -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); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,308 +0,0 @@
@@ -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; |
||||
} |
||||
} |
||||
} |
||||
@ -1,199 +0,0 @@
@@ -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")); |
||||
} |
||||
} |
||||
@ -0,0 +1,38 @@
@@ -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> |
||||
@ -1,22 +0,0 @@
@@ -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> |
||||
Loading…
Reference in new issue