SEC-133: Move portlet module out of sandbox
This commit is contained in:
+438
@@ -0,0 +1,438 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.context;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.portlet.ActionRequest;
|
||||
import javax.portlet.ActionResponse;
|
||||
import javax.portlet.PortletException;
|
||||
import javax.portlet.PortletRequest;
|
||||
import javax.portlet.PortletResponse;
|
||||
import javax.portlet.PortletSession;
|
||||
import javax.portlet.RenderRequest;
|
||||
import javax.portlet.RenderResponse;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.portlet.HandlerInterceptor;
|
||||
import org.springframework.web.portlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* <p>This interceptor populates the {@link SecurityContextHolder} with information obtained from the
|
||||
* <code>PortletSession</code>. It is applied to both <code>ActionRequest</code>s and
|
||||
* <code>RenderRequest</code>s</p>
|
||||
*
|
||||
* <p>The <code>PortletSession</code> will be queried to retrieve the <code>SecurityContext</code> that should
|
||||
* be stored against the <code>SecurityContextHolder</code> for the duration of the portlet request. At the
|
||||
* end of the request, any updates made to the <code>SecurityContextHolder</code> will be persisted back to the
|
||||
* <code>PortletSession</code> by this interceptor.</p>
|
||||
*
|
||||
* <p> If a valid <code>SecurityContext</code> cannot be obtained from the <code>PortletSession</code> for
|
||||
* whatever reason, a fresh <code>SecurityContext</code> will be created and used instead. The created object
|
||||
* will be of the instance defined by the {@link #setContext(Class)} method (which defaults to
|
||||
* {@link org.acegisecurity.context.SecurityContextImpl}. </p>
|
||||
*
|
||||
* <p>A <code>PortletSession</code> may be created by this interceptor if one does not already exist. If at the
|
||||
* end of the portlet request the <code>PortletSession</code> does not exist, one will <b>only</b> be created if
|
||||
* the current contents of the <code>SecurityContextHolder</code> are not the {@link java.lang.Object#equals}
|
||||
* to a <code>new</code> instance of {@link #context}. This avoids needless <code>PortletSession</code> creation,
|
||||
* and automates the storage of changes made to the <code>SecurityContextHolder</code>. There is one exception to
|
||||
* this rule, that is if the {@link #forceEagerSessionCreation} property is <code>true</code>, in which case
|
||||
* sessions will always be created irrespective of normal session-minimization logic (the default is
|
||||
* <code>false</code>, as this is resource intensive and not recommended).</p>
|
||||
*
|
||||
* <p>If for whatever reason no <code>PortletSession</code> should <b>ever</b> be created, the
|
||||
* {@link #allowSessionCreation} property should be set to <code>false</code>. Only do this if you really need
|
||||
* to conserve server memory and ensure all classes using the <code>SecurityContextHolder</code> are designed to
|
||||
* have no persistence of the <code>SecurityContext</code> between web requests. Please note that if
|
||||
* {@link #forceEagerSessionCreation} is <code>true</code>, the <code>allowSessionCreation</code> must also be
|
||||
* <code>true</code> (setting it to <code>false</code> will cause a startup-time error).</p>
|
||||
|
||||
* <p>This interceptor <b>must</b> be executed <b>before</p> any authentication processing mechanisms. These
|
||||
* mechanisms (specifically {@link org.acegisecurity.ui.portlet.PortletProcessingInterceptor}) expect the
|
||||
* <code>SecurityContextHolder</code> to contain a valid <code>SecurityContext</code> by the time they execute.</p>
|
||||
*
|
||||
* <p>An important nuance to this interceptor is that (by default) the <code>SecurityContext</code> is stored
|
||||
* into the <code>APPLICATION_SCOPE</code> of the <code>PortletSession</code>. This doesn't just mean you will be
|
||||
* sharing it with all the other portlets in your webapp (which is generally a good idea). It also means that (if
|
||||
* you have done all the other appropriate magic), you will share this <code>SecurityContext</code> with servlets in
|
||||
* your webapp. This is very useful if you have servlets serving images or processing AJAX calls from your portlets
|
||||
* since they can now use the {@link HttpSessionContextIntegrationFilter} to access the same <code>SecurityContext<code>
|
||||
* object from the session. This allows these calls to be secured as well as the portlet calls.</p>
|
||||
*
|
||||
* Much of the logic of this interceptor comes from the {@link HttpSessionContextIntegrationFilter} class which
|
||||
* fills the same purpose on the servlet side. Ben Alex and Patrick Burlson are listed as authors here because they
|
||||
* are the authors of that class and there are blocks of code that essentially identical between the two. (Making this
|
||||
* a good candidate for refactoring someday.)
|
||||
*
|
||||
* <p>Unlike <code>HttpSessionContextIntegrationFilter</code>, this interceptor does not check to see if it is
|
||||
* getting applied multiple times. This shouldn't be a problem since the application of interceptors is under the
|
||||
* control of the Spring Portlet MVC framework and tends to be more explicit and more predictable than the application
|
||||
* of filters. However, you should still be careful to only apply this inteceptor to your request once.</p>
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @author Ben Alex
|
||||
* @author Patrick Burleson
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class PortletSessionContextIntegrationInterceptor
|
||||
implements InitializingBean, HandlerInterceptor {
|
||||
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(PortletSessionContextIntegrationInterceptor.class);
|
||||
|
||||
public static final String ACEGI_SECURITY_CONTEXT_KEY = HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY;
|
||||
|
||||
private static final String SESSION_EXISTED = PortletSessionContextIntegrationInterceptor.class.getName() + ".SESSION_EXISTED";
|
||||
private static final String CONTEXT_HASHCODE = PortletSessionContextIntegrationInterceptor.class.getName() + ".CONTEXT_HASHCODE";
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private Class context = SecurityContextImpl.class;
|
||||
|
||||
private Object contextObject;
|
||||
|
||||
/**
|
||||
* Indicates if this interceptor can create a <code>PortletSession</code> if
|
||||
* needed (sessions are always created sparingly, but setting this value to
|
||||
* <code>false</code> will prohibit sessions from ever being created).
|
||||
* Defaults to <code>true</code>. Do not set to <code>false</code> if
|
||||
* you are have set {@link #forceEagerSessionCreation} to <code>true</code>,
|
||||
* as the properties would be in conflict.
|
||||
*/
|
||||
private boolean allowSessionCreation = true;
|
||||
|
||||
/**
|
||||
* Indicates if this interceptor is required to create a <code>PortletSession</code>
|
||||
* for every request before proceeding through the request process, even if the
|
||||
* <code>PortletSession</code> would not ordinarily have been created. By
|
||||
* default this is <code>false</code>, which is entirely appropriate for
|
||||
* most circumstances as you do not want a <code>PortletSession</code>
|
||||
* created unless the interceptor actually needs one. It is envisaged the main
|
||||
* situation in which this property would be set to <code>true</code> is
|
||||
* if using other interceptors that depend on a <code>PortletSession</code>
|
||||
* already existing. This is only required in specialized cases, so leave it set to
|
||||
* <code>false</code> unless you have an actual requirement and aware of the
|
||||
* session creation overhead.
|
||||
*/
|
||||
private boolean forceEagerSessionCreation = false;
|
||||
|
||||
/**
|
||||
* Indicates whether the <code>SecurityContext</code> will be cloned from
|
||||
* the <code>PortletSession</code>. The default is to simply reference
|
||||
* (the default is <code>false</code>). The default may cause issues if
|
||||
* concurrent threads need to have a different security identity from other
|
||||
* threads being concurrently processed that share the same
|
||||
* <code>PortletSession</code>. In most normal environments this does not
|
||||
* represent an issue, as changes to the security identity in one thread is
|
||||
* allowed to affect the security identity in other threads associated with
|
||||
* the same <code>PortletSession</code>. For unusual cases where this is not
|
||||
* permitted, change this value to <code>true</code> and ensure the
|
||||
* {@link #context} is set to a <code>SecurityContext</code> that
|
||||
* implements {@link Cloneable} and overrides the <code>clone()</code>
|
||||
* method.
|
||||
*/
|
||||
private boolean cloneFromPortletSession = false;
|
||||
|
||||
/**
|
||||
* Indicates wether the <code>APPLICATION_SCOPE</code> mode of the
|
||||
* <code>PortletSession</code> should be used for storing the
|
||||
* <code>SecurityContext</code>. The default is </code>true</code>.
|
||||
* This allows it to be shared between the portlets in the webapp and
|
||||
* potentially with servlets in the webapp as well. If this is set to
|
||||
* <code>false</code>, then the <code>PORTLET_SCOPE</code> will be used
|
||||
* instead.
|
||||
*/
|
||||
private boolean useApplicationScopePortletSession = true;
|
||||
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public PortletSessionContextIntegrationInterceptor() throws PortletException {
|
||||
this.contextObject = generateNewContext();
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
// check that the value of context is legal
|
||||
if ((this.context == null) || (!SecurityContext.class.isAssignableFrom(this.context))) {
|
||||
throw new IllegalArgumentException("context must be defined and implement SecurityContext "
|
||||
+ "(typically use org.acegisecurity.context.SecurityContextImpl; existing class is "
|
||||
+ this.context + ")");
|
||||
}
|
||||
|
||||
// check that session creation options make sense
|
||||
if ((forceEagerSessionCreation == true) && (allowSessionCreation == false)) {
|
||||
throw new IllegalArgumentException(
|
||||
"If using forceEagerSessionCreation, you must set allowSessionCreation to also be true");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean preHandleAction(ActionRequest request, ActionResponse response,
|
||||
Object handler) throws Exception {
|
||||
// call to common preHandle method
|
||||
return preHandle(request, response, handler);
|
||||
}
|
||||
|
||||
public boolean preHandleRender(RenderRequest request, RenderResponse response,
|
||||
Object handler) throws Exception {
|
||||
// call to common preHandle method
|
||||
return preHandle(request, response, handler);
|
||||
}
|
||||
|
||||
public void postHandleRender(RenderRequest request, RenderResponse response,
|
||||
Object handler, ModelAndView modelAndView) throws Exception {
|
||||
// no-op
|
||||
}
|
||||
|
||||
public void afterActionCompletion(ActionRequest request, ActionResponse response,
|
||||
Object handler, Exception ex) throws Exception {
|
||||
// call to common afterCompletion method
|
||||
afterCompletion(request, response, handler, ex);
|
||||
}
|
||||
|
||||
public void afterRenderCompletion(RenderRequest request, RenderResponse response,
|
||||
Object handler, Exception ex) throws Exception {
|
||||
// call to common afterCompletion method
|
||||
afterCompletion(request, response, handler, ex);
|
||||
}
|
||||
|
||||
|
||||
private boolean preHandle(PortletRequest request, PortletResponse response,
|
||||
Object handler) throws Exception {
|
||||
|
||||
PortletSession portletSession = null;
|
||||
boolean portletSessionExistedAtStartOfRequest = false;
|
||||
|
||||
// see if the portlet session already exists (or should be eagerly created)
|
||||
try {
|
||||
portletSession = request.getPortletSession(forceEagerSessionCreation);
|
||||
} catch (IllegalStateException ignored) {}
|
||||
|
||||
// if there is a session, then see if there is a context to bring in
|
||||
if (portletSession != null) {
|
||||
|
||||
// remember that the session already existed
|
||||
portletSessionExistedAtStartOfRequest = true;
|
||||
|
||||
// attempt to retrieve the context from the session
|
||||
Object contextFromSessionObject = portletSession.getAttribute(ACEGI_SECURITY_CONTEXT_KEY, portletSessionScope());
|
||||
|
||||
// if we got a context then place it into the holder
|
||||
if (contextFromSessionObject != null) {
|
||||
|
||||
// if we are supposed to clone it, then do so
|
||||
if (cloneFromPortletSession) {
|
||||
Assert.isInstanceOf(Cloneable.class, contextFromSessionObject,
|
||||
"Context must implement Clonable and provide a Object.clone() method");
|
||||
try {
|
||||
Method m = contextFromSessionObject.getClass().getMethod("clone", new Class[] {});
|
||||
if (!m.isAccessible()) {
|
||||
m.setAccessible(true);
|
||||
}
|
||||
contextFromSessionObject = m.invoke(contextFromSessionObject, new Object[] {});
|
||||
}
|
||||
catch (Exception ex) {
|
||||
ReflectionUtils.handleReflectionException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// if what we got is a valid context then place it into the holder, otherwise create a new one
|
||||
if (contextFromSessionObject instanceof SecurityContext) {
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Obtained from ACEGI_SECURITY_CONTEXT a valid SecurityContext and "
|
||||
+ "set to SecurityContextHolder: '" + contextFromSessionObject + "'");
|
||||
SecurityContextHolder.setContext((SecurityContext) contextFromSessionObject);
|
||||
} else {
|
||||
if (logger.isWarnEnabled())
|
||||
logger.warn("ACEGI_SECURITY_CONTEXT did not contain a SecurityContext but contained: '"
|
||||
+ contextFromSessionObject
|
||||
+ "'; are you improperly modifying the PortletSession directly "
|
||||
+ "(you should always use SecurityContextHolder) or using the PortletSession attribute "
|
||||
+ "reserved for this class? - new SecurityContext instance associated with "
|
||||
+ "SecurityContextHolder");
|
||||
SecurityContextHolder.setContext(generateNewContext());
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// there was no context in the session, so create a new context and put it in the holder
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("PortletSession returned null object for ACEGI_SECURITY_CONTEXT - new "
|
||||
+ "SecurityContext instance associated with SecurityContextHolder");
|
||||
SecurityContextHolder.setContext(generateNewContext());
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// there was no session, so create a new context and place it in the holder
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("No PortletSession currently exists - new SecurityContext instance "
|
||||
+ "associated with SecurityContextHolder");
|
||||
SecurityContextHolder.setContext(generateNewContext());
|
||||
|
||||
}
|
||||
|
||||
// place attributes onto the request to remember if the session existed and the hashcode of the context
|
||||
request.setAttribute(SESSION_EXISTED, new Boolean(portletSessionExistedAtStartOfRequest));
|
||||
request.setAttribute(CONTEXT_HASHCODE, new Integer(SecurityContextHolder.getContext().hashCode()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void afterCompletion(PortletRequest request, PortletResponse response,
|
||||
Object handler, Exception ex) throws Exception {
|
||||
|
||||
PortletSession portletSession = null;
|
||||
|
||||
// retrieve the attributes that remember if the session existed and the hashcode of the context
|
||||
boolean portletSessionExistedAtStartOfRequest = ((Boolean)request.getAttribute(SESSION_EXISTED)).booleanValue();
|
||||
int oldContextHashCode = ((Integer)request.getAttribute(CONTEXT_HASHCODE)).intValue();
|
||||
|
||||
// try to retrieve an existing portlet session
|
||||
try {
|
||||
portletSession = request.getPortletSession(false);
|
||||
} catch (IllegalStateException ignored) {}
|
||||
|
||||
// if there is now no session but there was one at the beginning then it must have been invalidated
|
||||
if ((portletSession == null) && portletSessionExistedAtStartOfRequest) {
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("PortletSession is now null, but was not null at start of request; "
|
||||
+ "session was invalidated, so do not create a new session");
|
||||
}
|
||||
|
||||
// create a new portlet session if we need to
|
||||
if ((portletSession == null) && !portletSessionExistedAtStartOfRequest) {
|
||||
|
||||
// if we're not allowed to create a new session, then report that
|
||||
if (!allowSessionCreation) {
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("The PortletSession is currently null, and the "
|
||||
+ "PortletSessionContextIntegrationInterceptor is prohibited from creating a PortletSession "
|
||||
+ "(because the allowSessionCreation property is false) - SecurityContext thus not "
|
||||
+ "stored for next request");
|
||||
}
|
||||
// if the context was changed during the request, then go ahead and create a session
|
||||
else if (!contextObject.equals(SecurityContextHolder.getContext())) {
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("PortletSession being created as SecurityContextHolder contents are non-default");
|
||||
try {
|
||||
portletSession = request.getPortletSession(true);
|
||||
} catch (IllegalStateException ignored) {}
|
||||
}
|
||||
// if nothing in the context changed, then don't bother to create a session
|
||||
else {
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("PortletSession is null, but SecurityContextHolder has not changed from default: ' "
|
||||
+ SecurityContextHolder.getContext()
|
||||
+ "'; not creating PortletSession or storing SecurityContextHolder contents");
|
||||
}
|
||||
}
|
||||
|
||||
// if the session exists and the context has changes, then store the context back into the session
|
||||
if ((portletSession != null)
|
||||
&& (SecurityContextHolder.getContext().hashCode() != oldContextHashCode)) {
|
||||
portletSession.setAttribute(ACEGI_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext(), portletSessionScope());
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("SecurityContext stored to PortletSession: '"
|
||||
+ SecurityContextHolder.getContext() + "'");
|
||||
}
|
||||
|
||||
// remove the contents of the holder
|
||||
SecurityContextHolder.clearContext();
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("SecurityContextHolder set to new context, as request processing completed");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new <code>SecurityContext</code> object. The specific class is
|
||||
* determined by the setting of the {@link #context} property.
|
||||
* @return the new <code>SecurityContext</code>
|
||||
* @throws PortletException if the creation throws an <code>InstantiationException</code> or
|
||||
* an <code>IllegalAccessException</code>, then this method will wrap them in a
|
||||
* <code>PortletException</code>
|
||||
*/
|
||||
public SecurityContext generateNewContext() throws PortletException {
|
||||
try {
|
||||
return (SecurityContext) this.context.newInstance();
|
||||
} catch (InstantiationException ie) {
|
||||
throw new PortletException(ie);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new PortletException(iae);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int portletSessionScope() {
|
||||
// return the appropriate scope setting based on our property value
|
||||
return (this.useApplicationScopePortletSession ?
|
||||
PortletSession.APPLICATION_SCOPE : PortletSession.PORTLET_SCOPE);
|
||||
}
|
||||
|
||||
|
||||
public Class getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public void setContext(Class secureContext) {
|
||||
this.context = secureContext;
|
||||
}
|
||||
|
||||
public boolean isAllowSessionCreation() {
|
||||
return allowSessionCreation;
|
||||
}
|
||||
|
||||
public void setAllowSessionCreation(boolean allowSessionCreation) {
|
||||
this.allowSessionCreation = allowSessionCreation;
|
||||
}
|
||||
|
||||
public boolean isForceEagerSessionCreation() {
|
||||
return forceEagerSessionCreation;
|
||||
}
|
||||
|
||||
public void setForceEagerSessionCreation(boolean forceEagerSessionCreation) {
|
||||
this.forceEagerSessionCreation = forceEagerSessionCreation;
|
||||
}
|
||||
|
||||
public boolean isCloneFromPortletSession() {
|
||||
return cloneFromPortletSession;
|
||||
}
|
||||
|
||||
public void setCloneFromPortletSession(boolean cloneFromPortletSession) {
|
||||
this.cloneFromPortletSession = cloneFromPortletSession;
|
||||
}
|
||||
|
||||
public boolean isUseApplicationScopePortletSession() {
|
||||
return useApplicationScopePortletSession;
|
||||
}
|
||||
|
||||
public void setUseApplicationScopePortletSession(
|
||||
boolean useApplicationScopePortletSession) {
|
||||
this.useApplicationScopePortletSession = useApplicationScopePortletSession;
|
||||
}
|
||||
|
||||
}
|
||||
+198
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.providers.portlet;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.portlet.PortletRequest;
|
||||
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
import org.acegisecurity.AuthenticationServiceException;
|
||||
import org.acegisecurity.BadCredentialsException;
|
||||
import org.acegisecurity.providers.AuthenticationProvider;
|
||||
import org.acegisecurity.providers.portlet.cache.NullUserCache;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* <p>Processes a JSR 168 Portlet authentication request. The request will typically
|
||||
* originate from {@link org.acegisecurity.ui.portlet.PortletProcessingInterceptor}.</p>
|
||||
*
|
||||
* <p>Be aware that this provider is trusting the portal and portlet container to handle
|
||||
* actual authentication. If a valid {@link PortletAuthenticationToken} is presented with
|
||||
* non-null principal and credentials, then the {@link #authenticate} method will succeed.</p>
|
||||
*
|
||||
* <p>If the <code>details</code> property of the requesting <code>Authentication</code>
|
||||
* object happens to be the <code>PortletRequest</code>, then this provider will place
|
||||
* the contents of the <code>USER_INFO</code> map from of the request attributes into
|
||||
* the <code>details</code> property of the authentication result.</p>
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class PortletAuthenticationProvider
|
||||
implements AuthenticationProvider, InitializingBean {
|
||||
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(PortletAuthenticationProvider.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private PortletAuthoritiesPopulator portletAuthoritiesPopulator;
|
||||
private UserCache userCache = new NullUserCache();
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(this.portletAuthoritiesPopulator, "An authorities populator must be set");
|
||||
Assert.notNull(this.userCache, "A user cache must be set");
|
||||
}
|
||||
|
||||
public boolean supports(Class authentication) {
|
||||
return PortletAuthenticationToken.class.isAssignableFrom(authentication);
|
||||
}
|
||||
|
||||
public Authentication authenticate(Authentication authentication)
|
||||
throws AuthenticationException {
|
||||
|
||||
// make sure we support the authentication
|
||||
if (!supports(authentication.getClass())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("portlet authentication request: " + authentication);
|
||||
|
||||
// make sure there is a valid principal in the authentication attempt
|
||||
Object principal = authentication.getPrincipal();
|
||||
if (principal == null) {
|
||||
throw new BadCredentialsException("No principal presented - user is not authenticated");
|
||||
}
|
||||
|
||||
// make sure there are valid credentials in the authentication attempt
|
||||
Object credentials = authentication.getCredentials();
|
||||
if (credentials == null) {
|
||||
throw new BadCredentialsException("No credentials presented - user is not authenticated");
|
||||
}
|
||||
|
||||
// determine the username string from the principal
|
||||
String username = getUsernameFromPrincipal(principal);
|
||||
if (username == null) {
|
||||
throw new BadCredentialsException("No username available - user is not authenticated");
|
||||
}
|
||||
|
||||
// try to retrieve the user from the cache
|
||||
UserDetails user = this.userCache.getUserFromCache(username);
|
||||
|
||||
// if the user is null then it wasn't in the cache so go get it
|
||||
if (user == null) {
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("user not found in the cache");
|
||||
|
||||
// get the user from the authorities populator
|
||||
user = this.portletAuthoritiesPopulator.getUserDetails(authentication);
|
||||
|
||||
if (user == null) {
|
||||
throw new AuthenticationServiceException(
|
||||
"portletAuthoritiesPopulator returned null, which is an interface contract violation");
|
||||
}
|
||||
|
||||
// store the result back in the cache
|
||||
this.userCache.putUserInCache(user);
|
||||
|
||||
} else {
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("got user from the cache");
|
||||
}
|
||||
|
||||
// build the resulting successful authentication token
|
||||
PortletAuthenticationToken result = new PortletAuthenticationToken(
|
||||
user, authentication.getCredentials(), user.getAuthorities());
|
||||
result.setAuthenticated(true);
|
||||
|
||||
// see if the detail property on the request is the PortletRequest
|
||||
if (authentication.getDetails() instanceof PortletRequest) {
|
||||
// if available, place the USER_INFO map into the details property of the result
|
||||
PortletRequest request = (PortletRequest)authentication.getDetails();
|
||||
Map userInfo = null;
|
||||
try {
|
||||
userInfo = (Map)request.getAttribute(PortletRequest.USER_INFO);
|
||||
} catch (Exception e) {
|
||||
logger.warn("unable to retrieve USER_INFO map from portlet request", e);
|
||||
}
|
||||
result.setDetails(userInfo);
|
||||
} else {
|
||||
// copy any other details information forward
|
||||
result.setDetails(authentication.getDetails());
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("portlet authentication succeeded: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method attempt to determine the username string from the principal object.
|
||||
* If the principal object is a {@link UserDetails} object then it will use the
|
||||
* {@link UserDetails#getUsername() method. If the principal object is a
|
||||
* {@link Principal} object then it will use the {@link Principal#getName()}
|
||||
* method. Otherwise it will simply call the <code>toString()<code> method
|
||||
* on the principal object and return that.
|
||||
* @param principal the principal object to inspect for a username
|
||||
* @return the determined username, or null if no principal is passed
|
||||
*/
|
||||
public static final String getUsernameFromPrincipal(Object principal) {
|
||||
if (principal == null) {
|
||||
return null;
|
||||
}
|
||||
if (principal instanceof UserDetails) {
|
||||
return ((UserDetails)principal).getUsername();
|
||||
}
|
||||
if (principal instanceof Principal) {
|
||||
return ((Principal)principal).getName();
|
||||
}
|
||||
return principal.toString();
|
||||
}
|
||||
|
||||
|
||||
public PortletAuthoritiesPopulator getPortletAuthoritiesPopulator() {
|
||||
return this.portletAuthoritiesPopulator;
|
||||
}
|
||||
|
||||
public void setPortletAuthoritiesPopulator(PortletAuthoritiesPopulator portletAuthoritiesPopulator) {
|
||||
this.portletAuthoritiesPopulator = portletAuthoritiesPopulator;
|
||||
}
|
||||
|
||||
public UserCache getUserCache() {
|
||||
return userCache;
|
||||
}
|
||||
|
||||
public void setUserCache(UserCache userCache) {
|
||||
this.userCache = userCache;
|
||||
}
|
||||
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.providers.portlet;
|
||||
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
import org.acegisecurity.providers.AbstractAuthenticationToken;
|
||||
|
||||
/**
|
||||
* <code>Authentication</code> implementation for JSR 168 Portlet authentication. <p>The
|
||||
* corresponding authentication provider is {@link PortletAuthenticationProvider}.</p>
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class PortletAuthenticationToken extends AbstractAuthenticationToken {
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Object principal;
|
||||
private Object credentials;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public PortletAuthenticationToken(Object principal, Object credentials, GrantedAuthority[] authorities) {
|
||||
super(authorities);
|
||||
this.principal = principal;
|
||||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public Object getPrincipal() {
|
||||
return this.principal;
|
||||
}
|
||||
|
||||
public Object getCredentials() {
|
||||
return this.credentials;
|
||||
}
|
||||
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.providers.portlet;
|
||||
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
|
||||
/**
|
||||
* Populates the <code>UserDetails</code> associated with the
|
||||
* portlet user presented by the portlet container.
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface PortletAuthoritiesPopulator {
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Obtains the granted authorities for the specified Authentication object.
|
||||
* <p>May throw any <code>AuthenticationException</code> or return <code>null</code>
|
||||
* if the authorities are unavailable.</p>
|
||||
* @param authentication the authentication object seeking authorities
|
||||
* @return the details of the indicated user (at minimum the granted authorities and the username)
|
||||
* @throws AuthenticationException if the user details are not available or the authentication is not valid for some reason
|
||||
*/
|
||||
public UserDetails getUserDetails(Authentication authentication) throws AuthenticationException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.providers.portlet;
|
||||
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
|
||||
/**
|
||||
* Provides a cache of {@link UserDetails} objects for the
|
||||
* {@link PortletAuthenticationProvider}.
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface UserCache {
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public UserDetails getUserFromCache(String username);
|
||||
|
||||
public void putUserInCache(UserDetails user);
|
||||
|
||||
public void removeUserFromCache(String username);
|
||||
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.providers.portlet.cache;
|
||||
|
||||
import net.sf.ehcache.Cache;
|
||||
import net.sf.ehcache.CacheException;
|
||||
import net.sf.ehcache.Element;
|
||||
|
||||
import org.acegisecurity.providers.portlet.UserCache;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* <code>UserCache</code> implementation for portlets that uses an injected
|
||||
* <a href="http://ehcache.sourceforge.net">ehcache</a>.
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class EhCacheBasedUserCache
|
||||
implements UserCache, InitializingBean {
|
||||
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(EhCacheBasedUserCache.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private Cache cache;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(cache, "cache mandatory");
|
||||
}
|
||||
|
||||
public UserDetails getUserFromCache(String username) {
|
||||
|
||||
Element element = null;
|
||||
|
||||
try {
|
||||
element = cache.get(username);
|
||||
} catch (CacheException cacheException) {
|
||||
throw new DataRetrievalFailureException("Cache failure: "
|
||||
+ cacheException.getMessage());
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Cache hit: " + (element != null) + "; username: " + username);
|
||||
|
||||
return (element != null ? (UserDetails) element.getValue() : null);
|
||||
}
|
||||
|
||||
public void putUserInCache(UserDetails user) {
|
||||
|
||||
Element element = new Element(user.getUsername(), user);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Cache put: " + element.getKey());
|
||||
|
||||
cache.put(element);
|
||||
}
|
||||
|
||||
public void removeUserFromCache(UserDetails user) {
|
||||
this.removeUserFromCache(user.getUsername());
|
||||
}
|
||||
|
||||
public void removeUserFromCache(String username) {
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Cache remove: " + username);
|
||||
cache.remove(username);
|
||||
}
|
||||
|
||||
|
||||
public Cache getCache() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
public void setCache(Cache cache) {
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.providers.portlet.cache;
|
||||
|
||||
import org.acegisecurity.providers.portlet.UserCache;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
|
||||
/**
|
||||
* <code>UserCache</code> implementation for portlets that does nothing.
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class NullUserCache implements UserCache {
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public UserDetails getUserFromCache(String username) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void putUserInCache(UserDetails user) {}
|
||||
|
||||
public void removeUserFromCache(String username) {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
User caches for the Portlet provider.
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
An authentication provider that can uses the security model in the Portlet 1.0 (JSR 168) Specification.
|
||||
</body>
|
||||
</html>
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.providers.portlet.populator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.portlet.PortletRequest;
|
||||
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
import org.acegisecurity.AuthenticationServiceException;
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
import org.acegisecurity.providers.portlet.PortletAuthenticationProvider;
|
||||
import org.acegisecurity.providers.portlet.PortletAuthoritiesPopulator;
|
||||
import org.acegisecurity.userdetails.User;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
|
||||
/**
|
||||
* <p>Populates the portlet authorities via role information from the portlet container.
|
||||
* Primarily it uses the <code>PortletRequest.isUserInRole(role)</code> method to
|
||||
* check if the user is in a list of configured roles.</p>
|
||||
*
|
||||
* <p>This bean has the following configurable properties:</p>
|
||||
* <ul>
|
||||
* <li><code>rolesToCheck</code> : A list of strings containing names of roles to check.
|
||||
* These roles must also be properly declared in a <security-role-ref> element
|
||||
* of the portlet descriptor in the portlet.xml file.</li>
|
||||
* <li><code>rolePrefix</code> : The prefix to be added onto each role name that as it is
|
||||
* added to the list of authorities. The default value is 'ROLE_'.</li>
|
||||
* <li><code>userRole</code> : The authority that all authenticated users will automatically
|
||||
* be granted. The default value is 'ROLE_USER'. Set this to null to avoid having any
|
||||
* value automatically populated.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>This populator depends on finding the <code>PortletRequest<code> when calling the
|
||||
* {@link Authentication#getDetails()} method on the object passed to
|
||||
* {@link #getUserDetails(Authentication)}. If not, it will throw an
|
||||
* {@link AuthenticationServiceException}.
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ContainerPortletAuthoritiesPopulator
|
||||
implements PortletAuthoritiesPopulator {
|
||||
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
public static final String DEFAULT_ROLE_PREFIX = "ROLE_";
|
||||
public static final String DEFAULT_USER_ROLE = "ROLE_USER";
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private List rolesToCheck;
|
||||
private String rolePrefix = DEFAULT_ROLE_PREFIX;
|
||||
private String userRole = DEFAULT_USER_ROLE;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public UserDetails getUserDetails(Authentication authentication)
|
||||
throws AuthenticationException {
|
||||
|
||||
// get the username and password for the authentication
|
||||
String username = PortletAuthenticationProvider.getUsernameFromPrincipal(authentication.getPrincipal());
|
||||
String password = authentication.getCredentials().toString();
|
||||
|
||||
// see if we can load authorities from the portlet request
|
||||
Object details = authentication.getDetails();
|
||||
if (!(details instanceof PortletRequest)) {
|
||||
throw new AuthenticationServiceException("expected Authentication.getDetails() to return a PortletRequest");
|
||||
}
|
||||
GrantedAuthority[] authorities = loadGrantedAuthorities((PortletRequest)details);
|
||||
|
||||
// construct and return the new user
|
||||
return new User(username, password, true, true, true, true, authorities);
|
||||
}
|
||||
|
||||
private GrantedAuthority[] loadGrantedAuthorities(PortletRequest request) {
|
||||
|
||||
// start the list and add the standard user role
|
||||
ArrayList authorities = new ArrayList();
|
||||
if (this.userRole != null && this.userRole.length() > 0)
|
||||
authorities.add(new GrantedAuthorityImpl(getUserRole()));
|
||||
|
||||
// iterate through the configured list of roles to check (if there is one)
|
||||
if (this.rolesToCheck != null) {
|
||||
for(Iterator i = this.rolesToCheck.iterator(); i.hasNext(); ) {
|
||||
String role = (String)i.next();
|
||||
|
||||
// if the request says the user has that role, then add it
|
||||
if (request.isUserInRole(role)) {
|
||||
authorities.add(new GrantedAuthorityImpl(getRolePrefix() + role));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// return the array of GrantedAuthority objects
|
||||
return (GrantedAuthority[])authorities.toArray(new GrantedAuthority[authorities.size()]);
|
||||
}
|
||||
|
||||
|
||||
public List getRolesToCheck() {
|
||||
return rolesToCheck;
|
||||
}
|
||||
|
||||
public void setRolesToCheck(List rolesToCheck) {
|
||||
this.rolesToCheck = rolesToCheck;
|
||||
}
|
||||
|
||||
public String getRolePrefix() {
|
||||
return rolePrefix;
|
||||
}
|
||||
|
||||
public void setRolePrefix(String rolePrefix) {
|
||||
this.rolePrefix = rolePrefix;
|
||||
}
|
||||
|
||||
public String getUserRole() {
|
||||
return userRole;
|
||||
}
|
||||
|
||||
public void setUserRole(String userRole) {
|
||||
this.userRole = userRole;
|
||||
}
|
||||
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.providers.portlet.populator;
|
||||
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
import org.acegisecurity.AuthenticationServiceException;
|
||||
import org.acegisecurity.providers.portlet.PortletAuthenticationProvider;
|
||||
import org.acegisecurity.providers.portlet.PortletAuthoritiesPopulator;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
import org.acegisecurity.userdetails.UserDetailsService;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Populates the portlet authorities via a {@link UserDetailsService}.
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class DaoPortletAuthoritiesPopulator
|
||||
implements PortletAuthoritiesPopulator, InitializingBean {
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(this.userDetailsService, "A userDetailsService must be set");
|
||||
}
|
||||
|
||||
public UserDetails getUserDetails(Authentication authentication)
|
||||
throws AuthenticationException {
|
||||
|
||||
// make sure the Authentication object is valid
|
||||
if (authentication == null || authentication.getPrincipal() == null) {
|
||||
throw new AuthenticationServiceException(
|
||||
"must pass valid Authentication object with non-null principal");
|
||||
}
|
||||
|
||||
// get the username from the principal
|
||||
String username = PortletAuthenticationProvider.getUsernameFromPrincipal(authentication.getPrincipal());
|
||||
|
||||
// call the UserDetailsService with the username
|
||||
return this.userDetailsService.loadUserByUsername(username);
|
||||
}
|
||||
|
||||
|
||||
public UserDetailsService getUserDetailsService() {
|
||||
return userDetailsService;
|
||||
}
|
||||
|
||||
public void setUserDetailsService(UserDetailsService userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
Implementations that populate GrantedAuthority[]s of Portlet authentications.
|
||||
</body>
|
||||
</html>
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.ui.portlet;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
import org.acegisecurity.ui.AuthenticationEntryPoint;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
/**
|
||||
* <p>In the case of relying on Portlet authentication to access Servlet resources
|
||||
* (such as embedded images or AJAX calls), the authentication should already
|
||||
* be in place by the time the security enforcement takes place.
|
||||
* So, if this class is ever called, then portlet-based authentication has
|
||||
* already failed. Therefore the <code>commence</code> method in this case will
|
||||
* always return <code>HttpServletResponse.SC_FORBIDDEN</code> (HTTP 403 error).
|
||||
*
|
||||
* @see org.acegisecurity.ui.ExceptionTranslationFilter
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class PortletProcessingFilterEntryPoint implements AuthenticationEntryPoint, Ordered {
|
||||
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(PortletProcessingFilterEntryPoint.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private int order = Integer.MAX_VALUE; // ~ default
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public int getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
public void commence(ServletRequest request, ServletResponse response,
|
||||
AuthenticationException authException) throws IOException, ServletException {
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("portlet entry point called. Rejecting access");
|
||||
|
||||
HttpServletResponse httpResponse = (HttpServletResponse)response;
|
||||
httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.ui.portlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.portlet.ActionRequest;
|
||||
import javax.portlet.ActionResponse;
|
||||
import javax.portlet.PortletRequest;
|
||||
import javax.portlet.PortletResponse;
|
||||
import javax.portlet.PortletSession;
|
||||
import javax.portlet.RenderRequest;
|
||||
import javax.portlet.RenderResponse;
|
||||
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
import org.acegisecurity.AuthenticationManager;
|
||||
import org.acegisecurity.context.SecurityContext;
|
||||
import org.acegisecurity.context.SecurityContextHolder;
|
||||
import org.acegisecurity.providers.portlet.PortletAuthenticationProvider;
|
||||
import org.acegisecurity.providers.portlet.PortletAuthenticationToken;
|
||||
import org.acegisecurity.providers.portlet.populator.ContainerPortletAuthoritiesPopulator;
|
||||
import org.acegisecurity.ui.AbstractProcessingFilter;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.portlet.HandlerInterceptor;
|
||||
import org.springframework.web.portlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* <p>This interceptor is responsible for processing portlet authentication requests. This
|
||||
* is the portlet equivalent of the <code>AuthenticationProcessingFilter</code> used for
|
||||
* traditional servlet-based web applications. It is applied to both <code>ActionRequest</code>s
|
||||
* and <code>RenderRequest</code>s alike. If authentication is successful, the resulting
|
||||
* {@link Authentication} object will be placed into the <code>SecurityContext</code>, which
|
||||
* is guaranteed to have already been created by an earlier interceptor. If authentication
|
||||
* fails, the <code>AuthenticationException</code> will be placed into the
|
||||
* <code>APPLICATION_SCOPE</code> of the <code>PortletSession</code> with the attribute defined
|
||||
* by {@link AbstractProcessingFilter#ACEGI_SECURITY_LAST_EXCEPTION_KEY}.</p>
|
||||
*
|
||||
* <p>Some portals do not properly provide the identity of the current user via the
|
||||
* <code>getRemoteUser()</code> or <code>getUserPrincipal()</code> methods of the
|
||||
* <code>PortletRequest</code>. In these cases they sometimes make it available in the
|
||||
* <code>USER_INFO</code> map provided as one of the attributes of the request. If this is
|
||||
* the case in your portal, you can specify a list of <code>USER_INFO</code> attributes
|
||||
* to check for the username via the <code>userNameAttributes</code> property of this bean.
|
||||
* You can also completely override the {@link #getPrincipalFromRequest(PortletRequest)}
|
||||
* and {@link #getCredentialsFromRequest(PortletRequest)} methods to suit the particular
|
||||
* behavior of your portal.</p>
|
||||
*
|
||||
* <p>This interceptor will put the <code>PortletRequest</code> object into the
|
||||
* <code>details<code> property of the <code>Authentication</code> object that is sent
|
||||
* as a request to the <code>AuthenticationManager</code>. This is done so that the request
|
||||
* is available to classes like {@link ContainerPortletAuthoritiesPopulator} that need
|
||||
* access to information from the portlet container. The {@link PortletAuthenticationProvider}
|
||||
* will replace this with the <code>USER_INFO</code> map in the resulting <code>Authentication</code>
|
||||
* object.</p>
|
||||
*
|
||||
* @see org.acegisecurity.ui.AbstractProcessingFilter
|
||||
* @see org.acegisecurity.ui.webapp.AuthenticationProcessingFilter
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class PortletProcessingInterceptor implements
|
||||
HandlerInterceptor, InitializingBean {
|
||||
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(PortletProcessingInterceptor.class);
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
private List userNameAttributes;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(authenticationManager, "An AuthenticationManager must be set");
|
||||
}
|
||||
|
||||
public boolean preHandleAction(ActionRequest request, ActionResponse response,
|
||||
Object handler) throws Exception {
|
||||
return preHandle(request, response, handler);
|
||||
}
|
||||
|
||||
public boolean preHandleRender(RenderRequest request,
|
||||
RenderResponse response, Object handler) throws Exception {
|
||||
return preHandle(request, response, handler);
|
||||
}
|
||||
|
||||
public void postHandleRender(RenderRequest request, RenderResponse response,
|
||||
Object handler, ModelAndView modelAndView) throws Exception {
|
||||
}
|
||||
|
||||
public void afterActionCompletion(ActionRequest request, ActionResponse response,
|
||||
Object handler, Exception ex) throws Exception {
|
||||
}
|
||||
|
||||
public void afterRenderCompletion(RenderRequest request, RenderResponse response,
|
||||
Object handler, Exception ex) throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Common preHandle method for both the action and render phases of the interceptor.
|
||||
*/
|
||||
private boolean preHandle(PortletRequest request, PortletResponse response,
|
||||
Object handler) throws Exception {
|
||||
|
||||
// get the SecurityContext
|
||||
SecurityContext ctx = SecurityContextHolder.getContext();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Checking secure context token: " + ctx.getAuthentication());
|
||||
|
||||
// if there is no existing Authentication object, then lets create one
|
||||
if (ctx.getAuthentication() == null) {
|
||||
|
||||
try {
|
||||
|
||||
// build the authentication request from the PortletRequest
|
||||
PortletAuthenticationToken authRequest = new PortletAuthenticationToken(
|
||||
getPrincipalFromRequest(request),
|
||||
getCredentialsFromRequest(request),
|
||||
null);
|
||||
|
||||
// put the PortletRequest into the authentication request as the "details"
|
||||
authRequest.setDetails(request);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Beginning authentication request for user '" + authRequest.getName() + "'");
|
||||
|
||||
onPreAuthentication(request, response);
|
||||
|
||||
// ask the authentication manager to authenticate the request
|
||||
// it will throw an AuthenticationException if it fails, otherwise it succeeded
|
||||
Authentication authResult = authenticationManager.authenticate(authRequest);
|
||||
|
||||
// process a successful authentication
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Authentication success: " + authResult);
|
||||
ctx.setAuthentication(authResult);
|
||||
onSuccessfulAuthentication(request, response, authResult);
|
||||
|
||||
} catch (AuthenticationException failed) {
|
||||
|
||||
// process an unsuccessful authentication
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Authentication failed - updating ContextHolder to contain null Authentication");
|
||||
ctx.setAuthentication(null);
|
||||
request.getPortletSession().setAttribute(
|
||||
AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY,
|
||||
failed, PortletSession.APPLICATION_SCOPE);
|
||||
onUnsuccessfulAuthentication(request, response, failed);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method attempts to extract a principal from the portlet request.
|
||||
* According to the JSR 168 spec, the <code>PortletRequest<code> should return the name
|
||||
* of the user in the <code>getRemoteUser()</code> method. It should also provide a
|
||||
* <code>java.security.Principal</code> object from the <code>getUserPrincipal()</code>
|
||||
* method. We will first try these to come up with a valid username.
|
||||
* <p>Unfortunately, some portals do not properly return these values for authenticated
|
||||
* users. So, if neither of those succeeds and if the <code>userNameAttributes</code>
|
||||
* property has been populated, then we will search through the <code>USER_INFO<code>
|
||||
* map from the request to see if we can find a valid username.
|
||||
* <p>This method can be overridden by subclasses to provide special handling
|
||||
* for portals with weak support for the JSR 168 spec.</p>
|
||||
* @param request the portlet request object
|
||||
* @return the determined principal object, or null if none found
|
||||
*/
|
||||
protected Object getPrincipalFromRequest(PortletRequest request) {
|
||||
|
||||
// first try getRemoteUser()
|
||||
String remoteUser = request.getRemoteUser();
|
||||
if (remoteUser != null) {
|
||||
return remoteUser;
|
||||
}
|
||||
|
||||
// next try getUserPrincipal()
|
||||
Principal userPrincipal = request.getUserPrincipal();
|
||||
if (userPrincipal != null) {
|
||||
String userPrincipalName = userPrincipal.getName();
|
||||
if (userPrincipalName != null) {
|
||||
return userPrincipalName;
|
||||
}
|
||||
}
|
||||
|
||||
// last try entries in USER_INFO if any attributes were defined
|
||||
if (this.userNameAttributes != null) {
|
||||
Map userInfo = null;
|
||||
try {
|
||||
userInfo = (Map)request.getAttribute(PortletRequest.USER_INFO);
|
||||
} catch (Exception e) {
|
||||
logger.warn("unable to retrieve USER_INFO map from portlet request", e);
|
||||
}
|
||||
if (userInfo != null) {
|
||||
Iterator i = this.userNameAttributes.iterator();
|
||||
while(i.hasNext()) {
|
||||
Object principal = (String)userInfo.get(i.next());
|
||||
if (principal != null) {
|
||||
return principal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// none found so return null
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method attempts to extract a credentials from the portlet request.
|
||||
* We are trusting the portal framework to authenticate the user, so all
|
||||
* we are really doing is trying to put something intelligent in here to
|
||||
* indicate the user is authenticated. According to the JSR 168 spec,
|
||||
* PortletRequest.getAuthType() should return a non-null value if the
|
||||
* user is authenticated and should be null if not authenticated. So we
|
||||
* will use this as the credentials and the token will be trusted as
|
||||
* authenticated if the credentials are not null.
|
||||
* <p>This method can be overridden by subclasses to provide special handling
|
||||
* for portals with weak support for the JSR 168 spec. If that is done,
|
||||
* be sure the value is non-null for authenticated users and null for
|
||||
* non-authenticated users.</p>
|
||||
* @param request the portlet request object
|
||||
* @return the determined credentials object, or null if none found
|
||||
*/
|
||||
protected Object getCredentialsFromRequest(PortletRequest request) {
|
||||
return request.getAuthType();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback for custom processing prior to the authentication attempt.
|
||||
* @param request the portlet request to be authenticated
|
||||
* @param response the portlet response to be authenticated
|
||||
* @throws AuthenticationException to indicate that authentication attempt is not valid and should be terminated
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void onPreAuthentication(PortletRequest request, PortletResponse response)
|
||||
throws AuthenticationException, IOException {}
|
||||
|
||||
/**
|
||||
* Callback for custom processing after a successful authentication attempt.
|
||||
* @param request the portlet request that was authenticated
|
||||
* @param response the portlet response that was authenticated
|
||||
* @param authResult the resulting Authentication object
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void onSuccessfulAuthentication(PortletRequest request, PortletResponse response, Authentication authResult)
|
||||
throws IOException {}
|
||||
|
||||
/**
|
||||
* Callback for custom processing after an unsuccessful authentication attempt.
|
||||
* @param request the portlet request that failed authentication
|
||||
* @param response the portlet response that failed authentication
|
||||
* @param failed the AuthenticationException that occurred
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void onUnsuccessfulAuthentication(PortletRequest request, PortletResponse response, AuthenticationException failed)
|
||||
throws IOException {}
|
||||
|
||||
|
||||
public AuthenticationManager getAuthenticationManager() {
|
||||
return authenticationManager;
|
||||
}
|
||||
|
||||
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
|
||||
this.authenticationManager = authenticationManager;
|
||||
}
|
||||
|
||||
public List getUserNameAttributes() {
|
||||
return userNameAttributes;
|
||||
}
|
||||
|
||||
public void setUserNameAttributes(List userNameAttributes) {
|
||||
this.userNameAttributes = userNameAttributes;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
Authentication interceptor (and related classes) for use with the Portlet 1.0 (JSR 168) Specification.
|
||||
</body>
|
||||
</html>
|
||||
+372
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.context;
|
||||
|
||||
import javax.portlet.PortletSession;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
import org.acegisecurity.providers.portlet.PortletAuthenticationToken;
|
||||
import org.acegisecurity.providers.portlet.PortletTestUtils;
|
||||
import org.acegisecurity.userdetails.User;
|
||||
import org.springframework.mock.web.portlet.MockActionRequest;
|
||||
import org.springframework.mock.web.portlet.MockActionResponse;
|
||||
import org.springframework.mock.web.portlet.MockRenderRequest;
|
||||
import org.springframework.mock.web.portlet.MockRenderResponse;
|
||||
|
||||
/**
|
||||
* Tests {@link PortletSessionContextIntegrationInterceptor}.
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class PortletSessionContextIntegrationInterceptorTests extends TestCase {
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public PortletSessionContextIntegrationInterceptorTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public PortletSessionContextIntegrationInterceptorTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
public void testDetectsIncompatibleSessionProperties() throws Exception {
|
||||
PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor();
|
||||
try {
|
||||
interceptor.setAllowSessionCreation(false);
|
||||
interceptor.setForceEagerSessionCreation(true);
|
||||
interceptor.afterPropertiesSet();
|
||||
fail("Shown have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
// ignore
|
||||
}
|
||||
interceptor.setAllowSessionCreation(true);
|
||||
interceptor.afterPropertiesSet();
|
||||
}
|
||||
|
||||
public void testDetectsMissingOrInvalidContext() throws Exception {
|
||||
PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor();
|
||||
try {
|
||||
interceptor.setContext(null);
|
||||
interceptor.afterPropertiesSet();
|
||||
fail("Shown have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
// ignore
|
||||
}
|
||||
try {
|
||||
interceptor.setContext(Integer.class);
|
||||
assertEquals(Integer.class, interceptor.getContext());
|
||||
interceptor.afterPropertiesSet();
|
||||
fail("Shown have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
public void testNormalRenderRequestProcessing() throws Exception {
|
||||
|
||||
// Build an Authentication object we simulate came from PortletSession
|
||||
PortletAuthenticationToken sessionPrincipal = PortletTestUtils.createAuthenticatedToken();
|
||||
PortletAuthenticationToken baselinePrincipal = PortletTestUtils.createAuthenticatedToken();
|
||||
|
||||
// Build a Context to store in PortletSession (simulating prior request)
|
||||
SecurityContext sc = new SecurityContextImpl();
|
||||
sc.setAuthentication(sessionPrincipal);
|
||||
|
||||
// Build mock request and response
|
||||
MockRenderRequest request = PortletTestUtils.createRenderRequest();
|
||||
MockRenderResponse response = PortletTestUtils.createRenderResponse();
|
||||
request.getPortletSession().setAttribute(
|
||||
PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY,
|
||||
sc, PortletSession.APPLICATION_SCOPE);
|
||||
|
||||
// Prepare interceptor
|
||||
PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor();
|
||||
interceptor.afterPropertiesSet();
|
||||
|
||||
// Verify the SecurityContextHolder starts empty
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
// Run preHandleRender phase and verify SecurityContextHolder contains our Authentication
|
||||
interceptor.preHandleRender(request, response, null);
|
||||
assertEquals(baselinePrincipal, SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
// Run postHandleRender phase and verify the SecurityContextHolder still contains our Authentication
|
||||
interceptor.postHandleRender(request, response, null, null);
|
||||
assertEquals(baselinePrincipal, SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
// Run afterRenderCompletion phase and verify the SecurityContextHolder is empty
|
||||
interceptor.afterRenderCompletion(request, response, null, null);
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
public void testNormalActionRequestProcessing() throws Exception {
|
||||
|
||||
// Build an Authentication object we simulate came from PortletSession
|
||||
PortletAuthenticationToken sessionPrincipal = PortletTestUtils.createAuthenticatedToken();
|
||||
PortletAuthenticationToken baselinePrincipal = PortletTestUtils.createAuthenticatedToken();
|
||||
|
||||
// Build a Context to store in PortletSession (simulating prior request)
|
||||
SecurityContext sc = new SecurityContextImpl();
|
||||
sc.setAuthentication(sessionPrincipal);
|
||||
|
||||
// Build mock request and response
|
||||
MockActionRequest request = PortletTestUtils.createActionRequest();
|
||||
MockActionResponse response = PortletTestUtils.createActionResponse();
|
||||
request.getPortletSession().setAttribute(
|
||||
PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY,
|
||||
sc, PortletSession.APPLICATION_SCOPE);
|
||||
|
||||
// Prepare interceptor
|
||||
PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor();
|
||||
interceptor.afterPropertiesSet();
|
||||
|
||||
// Verify the SecurityContextHolder starts empty
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
// Run preHandleAction phase and verify SecurityContextHolder contains our Authentication
|
||||
interceptor.preHandleAction(request, response, null);
|
||||
assertEquals(baselinePrincipal, SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
// Run afterActionCompletion phase and verify the SecurityContextHolder is empty
|
||||
interceptor.afterActionCompletion(request, response, null, null);
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
public void testUpdatesCopiedBackIntoSession() throws Exception {
|
||||
|
||||
// Build an Authentication object we simulate came from PortletSession
|
||||
PortletAuthenticationToken sessionPrincipal = PortletTestUtils.createAuthenticatedToken();
|
||||
PortletAuthenticationToken baselinePrincipal = PortletTestUtils.createAuthenticatedToken();
|
||||
|
||||
// Build a Context to store in PortletSession (simulating prior request)
|
||||
SecurityContext sc = new SecurityContextImpl();
|
||||
sc.setAuthentication(sessionPrincipal);
|
||||
|
||||
// Build mock request and response
|
||||
MockActionRequest request = PortletTestUtils.createActionRequest();
|
||||
MockActionResponse response = PortletTestUtils.createActionResponse();
|
||||
request.getPortletSession().setAttribute(
|
||||
PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY,
|
||||
sc, PortletSession.APPLICATION_SCOPE);
|
||||
|
||||
// Prepare interceptor
|
||||
PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor();
|
||||
interceptor.afterPropertiesSet();
|
||||
|
||||
// Verify the SecurityContextHolder starts empty
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
// Run preHandleAction phase and verify SecurityContextHolder contains our Authentication
|
||||
interceptor.preHandleAction(request, response, null);
|
||||
assertEquals(baselinePrincipal, SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
// Perform updates to principal
|
||||
sessionPrincipal = PortletTestUtils.createAuthenticatedToken(
|
||||
new User(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, true, true, true, true,
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("UPDATEDROLE1")}));
|
||||
baselinePrincipal = PortletTestUtils.createAuthenticatedToken(
|
||||
new User(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, true, true, true, true,
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("UPDATEDROLE1")}));
|
||||
|
||||
// Store updated principal into SecurityContextHolder
|
||||
SecurityContextHolder.getContext().setAuthentication(sessionPrincipal);
|
||||
|
||||
// Run afterActionCompletion phase and verify the SecurityContextHolder is empty
|
||||
interceptor.afterActionCompletion(request, response, null, null);
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
// Verify the new principal is stored in the session
|
||||
sc = (SecurityContext)request.getPortletSession().getAttribute(
|
||||
PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY,
|
||||
PortletSession.APPLICATION_SCOPE);
|
||||
assertEquals(baselinePrincipal, sc.getAuthentication());
|
||||
}
|
||||
|
||||
public void testPortletSessionCreatedWhenContextHolderChanges() throws Exception {
|
||||
|
||||
// Build mock request and response
|
||||
MockActionRequest request = PortletTestUtils.createActionRequest();
|
||||
MockActionResponse response = PortletTestUtils.createActionResponse();
|
||||
|
||||
// Prepare the interceptor
|
||||
PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor();
|
||||
interceptor.afterPropertiesSet();
|
||||
|
||||
// Execute the interceptor
|
||||
interceptor.preHandleAction(request, response, null);
|
||||
PortletAuthenticationToken principal = PortletTestUtils.createAuthenticatedToken();
|
||||
SecurityContextHolder.getContext().setAuthentication(principal);
|
||||
interceptor.afterActionCompletion(request, response, null, null);
|
||||
|
||||
// Verify Authentication is in the PortletSession
|
||||
SecurityContext sc = (SecurityContext)request.getPortletSession(false).
|
||||
getAttribute(PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, PortletSession.APPLICATION_SCOPE);
|
||||
assertEquals(principal, ((SecurityContext)sc).getAuthentication());
|
||||
}
|
||||
|
||||
public void testPortletSessionEagerlyCreatedWhenDirected() throws Exception {
|
||||
|
||||
// Build mock request and response
|
||||
MockActionRequest request = PortletTestUtils.createActionRequest();
|
||||
MockActionResponse response = PortletTestUtils.createActionResponse();
|
||||
|
||||
// Prepare the interceptor
|
||||
PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor();
|
||||
interceptor.setForceEagerSessionCreation(true); // non-default
|
||||
interceptor.afterPropertiesSet();
|
||||
|
||||
// Execute the interceptor
|
||||
interceptor.preHandleAction(request, response, null);
|
||||
interceptor.afterActionCompletion(request, response, null, null);
|
||||
|
||||
// Check the session is not null
|
||||
assertNotNull(request.getPortletSession(false));
|
||||
}
|
||||
|
||||
public void testPortletSessionNotCreatedUnlessContextHolderChanges() throws Exception {
|
||||
|
||||
// Build mock request and response
|
||||
MockActionRequest request = PortletTestUtils.createActionRequest();
|
||||
MockActionResponse response = PortletTestUtils.createActionResponse();
|
||||
|
||||
// Prepare the interceptor
|
||||
PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor();
|
||||
interceptor.afterPropertiesSet();
|
||||
|
||||
// Execute the interceptor
|
||||
interceptor.preHandleAction(request, response, null);
|
||||
interceptor.afterActionCompletion(request, response, null, null);
|
||||
|
||||
// Check the session is null
|
||||
assertNull(request.getPortletSession(false));
|
||||
}
|
||||
|
||||
public void testPortletSessionWithNonContextInWellKnownLocationIsOverwritten()
|
||||
throws Exception {
|
||||
|
||||
// Build mock request and response
|
||||
MockActionRequest request = PortletTestUtils.createActionRequest();
|
||||
MockActionResponse response = PortletTestUtils.createActionResponse();
|
||||
request.getPortletSession().setAttribute(
|
||||
PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY,
|
||||
"NOT_A_CONTEXT_OBJECT", PortletSession.APPLICATION_SCOPE);
|
||||
|
||||
// Prepare the interceptor
|
||||
PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor();
|
||||
interceptor.afterPropertiesSet();
|
||||
|
||||
// Execute the interceptor
|
||||
interceptor.preHandleAction(request, response, null);
|
||||
PortletAuthenticationToken principal = PortletTestUtils.createAuthenticatedToken();
|
||||
SecurityContextHolder.getContext().setAuthentication(principal);
|
||||
interceptor.afterActionCompletion(request, response, null, null);
|
||||
|
||||
// Verify Authentication is in the PortletSession
|
||||
SecurityContext sc = (SecurityContext)request.getPortletSession(false).
|
||||
getAttribute(PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, PortletSession.APPLICATION_SCOPE);
|
||||
assertEquals(principal, ((SecurityContext)sc).getAuthentication());
|
||||
}
|
||||
|
||||
public void testPortletSessionCreationNotAllowed() throws Exception {
|
||||
|
||||
// Build mock request and response
|
||||
MockActionRequest request = PortletTestUtils.createActionRequest();
|
||||
MockActionResponse response = PortletTestUtils.createActionResponse();
|
||||
|
||||
// Prepare the interceptor
|
||||
PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor();
|
||||
interceptor.setAllowSessionCreation(false); // non-default
|
||||
interceptor.afterPropertiesSet();
|
||||
|
||||
// Execute the interceptor
|
||||
interceptor.preHandleAction(request, response, null);
|
||||
PortletAuthenticationToken principal = PortletTestUtils.createAuthenticatedToken();
|
||||
SecurityContextHolder.getContext().setAuthentication(principal);
|
||||
interceptor.afterActionCompletion(request, response, null, null);
|
||||
|
||||
// Check the session is null
|
||||
assertNull(request.getPortletSession(false));
|
||||
}
|
||||
|
||||
public void testUsePortletScopeSession() throws Exception {
|
||||
|
||||
// Build an Authentication object we simulate came from PortletSession
|
||||
PortletAuthenticationToken sessionPrincipal = PortletTestUtils.createAuthenticatedToken();
|
||||
PortletAuthenticationToken baselinePrincipal = PortletTestUtils.createAuthenticatedToken();
|
||||
|
||||
// Build a Context to store in PortletSession (simulating prior request)
|
||||
SecurityContext sc = new SecurityContextImpl();
|
||||
sc.setAuthentication(sessionPrincipal);
|
||||
|
||||
// Build mock request and response
|
||||
MockActionRequest request = PortletTestUtils.createActionRequest();
|
||||
MockActionResponse response = PortletTestUtils.createActionResponse();
|
||||
request.getPortletSession().setAttribute(
|
||||
PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY,
|
||||
sc, PortletSession.PORTLET_SCOPE);
|
||||
|
||||
// Prepare interceptor
|
||||
PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor();
|
||||
interceptor.setUseApplicationScopePortletSession(false); // non-default
|
||||
interceptor.afterPropertiesSet();
|
||||
|
||||
// Run preHandleAction phase and verify SecurityContextHolder contains our Authentication
|
||||
interceptor.preHandleAction(request, response, null);
|
||||
assertEquals(baselinePrincipal, SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
// Perform updates to principal
|
||||
sessionPrincipal = PortletTestUtils.createAuthenticatedToken(
|
||||
new User(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, true, true, true, true,
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("UPDATEDROLE1")}));
|
||||
baselinePrincipal = PortletTestUtils.createAuthenticatedToken(
|
||||
new User(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, true, true, true, true,
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("UPDATEDROLE1")}));
|
||||
|
||||
// Store updated principal into SecurityContextHolder
|
||||
SecurityContextHolder.getContext().setAuthentication(sessionPrincipal);
|
||||
|
||||
// Run afterActionCompletion phase and verify the SecurityContextHolder is empty
|
||||
interceptor.afterActionCompletion(request, response, null, null);
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
// Verify the new principal is stored in the session
|
||||
sc = (SecurityContext)request.getPortletSession().getAttribute(
|
||||
PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY,
|
||||
PortletSession.PORTLET_SCOPE);
|
||||
assertEquals(baselinePrincipal, sc.getAuthentication());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.providers.portlet;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
import org.acegisecurity.BadCredentialsException;
|
||||
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
|
||||
/**
|
||||
* Tests {@link PortletAuthenticationProvider}
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class PortletAuthenticationProviderTests extends TestCase {
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public PortletAuthenticationProviderTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public PortletAuthenticationProviderTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void testRequiresPopulator() throws Exception {
|
||||
PortletAuthenticationProvider provider = new PortletAuthenticationProvider();
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException failed) {
|
||||
//ignored
|
||||
}
|
||||
}
|
||||
|
||||
public void testNormalOperation() throws Exception {
|
||||
PortletAuthenticationProvider provider = new PortletAuthenticationProvider();
|
||||
provider.setPortletAuthoritiesPopulator(new MockAuthoritiesPopulator(false));
|
||||
provider.afterPropertiesSet();
|
||||
Authentication result = provider.authenticate(PortletTestUtils.createToken());
|
||||
assertNotNull(result);
|
||||
assertNotNull(result.getAuthorities());
|
||||
}
|
||||
|
||||
public void testAuthenticationIsNullWithUnsupportedToken() {
|
||||
PortletAuthenticationProvider provider = new PortletAuthenticationProvider();
|
||||
Authentication request = new UsernamePasswordAuthenticationToken(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED);
|
||||
Authentication result = provider.authenticate(request);
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
public void testFailsWithNoCredentials() {
|
||||
PortletAuthenticationProvider provider = new PortletAuthenticationProvider();
|
||||
provider.setPortletAuthoritiesPopulator(new MockAuthoritiesPopulator(false));
|
||||
try {
|
||||
provider.authenticate(new PortletAuthenticationToken(PortletTestUtils.TESTUSER, null, null));
|
||||
fail("Should have thrown BadCredentialsException");
|
||||
} catch (BadCredentialsException e) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
|
||||
public void testPopulatorRejectionCausesFailure() throws Exception {
|
||||
PortletAuthenticationProvider provider = new PortletAuthenticationProvider();
|
||||
provider.setPortletAuthoritiesPopulator(new MockAuthoritiesPopulator(true));
|
||||
try {
|
||||
provider.authenticate(PortletTestUtils.createToken());
|
||||
fail("Should have thrown BadCredentialsException");
|
||||
} catch (BadCredentialsException e) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
public static class MockAuthoritiesPopulator implements PortletAuthoritiesPopulator {
|
||||
|
||||
private boolean reject = false;
|
||||
|
||||
public MockAuthoritiesPopulator (boolean reject) {
|
||||
this.reject = reject;
|
||||
}
|
||||
|
||||
public UserDetails getUserDetails(Authentication authentication)
|
||||
throws AuthenticationException {
|
||||
if (authentication.getCredentials() == null)
|
||||
throw new BadCredentialsException("Invalid Credentials");
|
||||
if (reject)
|
||||
throw new BadCredentialsException("Authentication Rejected");
|
||||
return PortletTestUtils.createUser();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.providers.portlet;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Tests for {@link PortletAuthenticationToken}.
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class PortletAuthenticationTokenTests extends TestCase {
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public PortletAuthenticationTokenTests() {}
|
||||
|
||||
public PortletAuthenticationTokenTests(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testPrincipal() throws Exception {
|
||||
PortletAuthenticationToken token = PortletTestUtils.createToken();
|
||||
assertEquals(PortletTestUtils.TESTUSER, token.getPrincipal());
|
||||
}
|
||||
|
||||
public void testCredentials() throws Exception {
|
||||
PortletAuthenticationToken token = PortletTestUtils.createToken();
|
||||
assertEquals(PortletTestUtils.TESTCRED, token.getCredentials());
|
||||
}
|
||||
|
||||
public void testAuthenticated() throws Exception {
|
||||
PortletAuthenticationToken token = PortletTestUtils.createToken();
|
||||
assertTrue(!token.isAuthenticated());
|
||||
token.setAuthenticated(true);
|
||||
assertTrue(token.isAuthenticated());
|
||||
token.setAuthenticated(false);
|
||||
assertTrue(!token.isAuthenticated());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.providers.portlet;
|
||||
|
||||
import javax.portlet.PortletRequest;
|
||||
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
import org.acegisecurity.context.SecurityContext;
|
||||
import org.acegisecurity.context.SecurityContextHolder;
|
||||
import org.acegisecurity.context.SecurityContextImpl;
|
||||
import org.acegisecurity.providers.TestingAuthenticationToken;
|
||||
import org.acegisecurity.userdetails.User;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
import org.springframework.mock.web.portlet.MockActionRequest;
|
||||
import org.springframework.mock.web.portlet.MockActionResponse;
|
||||
import org.springframework.mock.web.portlet.MockPortletRequest;
|
||||
import org.springframework.mock.web.portlet.MockRenderRequest;
|
||||
import org.springframework.mock.web.portlet.MockRenderResponse;
|
||||
|
||||
/**
|
||||
* Utilities for testing Portlet (JSR 168) based security.
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class PortletTestUtils {
|
||||
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
public static final String PORTALROLE1 = "ONE";
|
||||
public static final String PORTALROLE2 = "TWO";
|
||||
|
||||
public static final String TESTUSER = "testuser";
|
||||
public static final String TESTCRED = PortletRequest.FORM_AUTH;
|
||||
public static final String TESTROLE1 = "ROLE_" + PORTALROLE1;
|
||||
public static final String TESTROLE2 = "ROLE_" + PORTALROLE2;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public static UserDetails createUser() {
|
||||
return new User(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, true, true, true, true,
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl(TESTROLE1), new GrantedAuthorityImpl(TESTROLE2)});
|
||||
}
|
||||
|
||||
public static void applyPortletRequestSecurity(MockPortletRequest request) {
|
||||
request.setRemoteUser(TESTUSER);
|
||||
request.setUserPrincipal(new TestingAuthenticationToken(TESTUSER, TESTCRED, null));
|
||||
request.addUserRole(PORTALROLE1);
|
||||
request.addUserRole(PORTALROLE2);
|
||||
request.setAuthType(PortletRequest.FORM_AUTH);
|
||||
}
|
||||
|
||||
public static MockRenderRequest createRenderRequest() {
|
||||
MockRenderRequest request = new MockRenderRequest();
|
||||
applyPortletRequestSecurity(request);
|
||||
return request;
|
||||
}
|
||||
|
||||
public static MockRenderResponse createRenderResponse() {
|
||||
MockRenderResponse response = new MockRenderResponse();
|
||||
return response;
|
||||
}
|
||||
|
||||
public static MockActionRequest createActionRequest() {
|
||||
MockActionRequest request = new MockActionRequest();
|
||||
applyPortletRequestSecurity(request);
|
||||
return request;
|
||||
}
|
||||
|
||||
public static MockActionResponse createActionResponse() {
|
||||
MockActionResponse response = new MockActionResponse();
|
||||
return response;
|
||||
}
|
||||
|
||||
public static PortletAuthenticationToken createToken(PortletRequest request) {
|
||||
PortletAuthenticationToken token = new PortletAuthenticationToken(TESTUSER, TESTCRED, null);
|
||||
token.setDetails(request);
|
||||
return token;
|
||||
}
|
||||
|
||||
public static PortletAuthenticationToken createToken() {
|
||||
MockRenderRequest request = createRenderRequest();
|
||||
return createToken(request);
|
||||
}
|
||||
|
||||
public static PortletAuthenticationToken createAuthenticatedToken(UserDetails user) {
|
||||
PortletAuthenticationToken result = new PortletAuthenticationToken(
|
||||
user, user.getPassword(), user.getAuthorities());
|
||||
result.setAuthenticated(true);
|
||||
return result;
|
||||
}
|
||||
public static PortletAuthenticationToken createAuthenticatedToken() {
|
||||
return createAuthenticatedToken(createUser());
|
||||
}
|
||||
|
||||
public static void setupSecurityContext(PortletRequest request) {
|
||||
PortletAuthenticationToken token = createToken(request);
|
||||
SecurityContext context = new SecurityContextImpl();
|
||||
context.setAuthentication(token);
|
||||
SecurityContextHolder.setContext(context);
|
||||
}
|
||||
|
||||
public static void setupSecurityContext() {
|
||||
MockRenderRequest request = createRenderRequest();
|
||||
setupSecurityContext(request);
|
||||
}
|
||||
|
||||
public static void cleanupSecurityContext() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.providers.portlet.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import net.sf.ehcache.Cache;
|
||||
|
||||
import org.acegisecurity.providers.portlet.PortletTestUtils;
|
||||
import org.springframework.cache.ehcache.EhCacheFactoryBean;
|
||||
|
||||
/**
|
||||
* Tests for {@link EhCacheBasedPortletUserCache}.
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class EhCacheBasedUserCacheTests extends TestCase {
|
||||
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static EhCacheFactoryBean cacheFactory;
|
||||
|
||||
static {
|
||||
cacheFactory = new EhCacheFactoryBean();
|
||||
cacheFactory.setCacheName("portletUserCache");
|
||||
try {
|
||||
cacheFactory.afterPropertiesSet();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("unable to initialize cache factory", e);
|
||||
}
|
||||
}
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public EhCacheBasedUserCacheTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public EhCacheBasedUserCacheTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
private Cache getCache() {
|
||||
return (Cache)cacheFactory.getObject();
|
||||
}
|
||||
|
||||
public void testCacheOperation() throws Exception {
|
||||
|
||||
// Create the cache
|
||||
EhCacheBasedUserCache cache = new EhCacheBasedUserCache();
|
||||
cache.setCache(getCache());
|
||||
cache.afterPropertiesSet();
|
||||
|
||||
// Check it gets stored in the cache
|
||||
cache.putUserInCache(PortletTestUtils.createUser());
|
||||
assertEquals(PortletTestUtils.TESTCRED,
|
||||
cache.getUserFromCache(PortletTestUtils.TESTUSER).getPassword());
|
||||
|
||||
// Check it gets removed from the cache
|
||||
cache.removeUserFromCache(PortletTestUtils.TESTUSER);
|
||||
assertNull(cache.getUserFromCache(PortletTestUtils.TESTUSER));
|
||||
|
||||
// Check it doesn't return values for null user
|
||||
assertNull(cache.getUserFromCache(null));
|
||||
}
|
||||
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.providers.portlet.populator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.acegisecurity.AuthenticationServiceException;
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
import org.acegisecurity.providers.portlet.PortletAuthenticationToken;
|
||||
import org.acegisecurity.providers.portlet.PortletTestUtils;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
|
||||
|
||||
/**
|
||||
* Tests for {@link ContainerPortletAuthoritiesPopulator}
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ContainerPortletAuthoritiesPopulatorTests extends TestCase {
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public ContainerPortletAuthoritiesPopulatorTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ContainerPortletAuthoritiesPopulatorTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
private List createRolesToCheck() {
|
||||
ArrayList rolesToCheck = new ArrayList();
|
||||
rolesToCheck.add(PortletTestUtils.PORTALROLE1);
|
||||
rolesToCheck.add("BOGUS1");
|
||||
rolesToCheck.add(PortletTestUtils.PORTALROLE2);
|
||||
rolesToCheck.add("BOGUS2");
|
||||
return rolesToCheck;
|
||||
}
|
||||
|
||||
public void testGetGrantedAuthorities() throws Exception {
|
||||
ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator();
|
||||
UserDetails results = populator.getUserDetails(PortletTestUtils.createToken());
|
||||
assertEquals(1, results.getAuthorities().length);
|
||||
assertEquals(new GrantedAuthorityImpl(ContainerPortletAuthoritiesPopulator.DEFAULT_USER_ROLE), results.getAuthorities()[0]);
|
||||
}
|
||||
|
||||
public void testGetGrantedAuthoritiesCheckRoles() throws Exception {
|
||||
ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator();
|
||||
populator.setRolesToCheck(createRolesToCheck());
|
||||
UserDetails results = populator.getUserDetails(PortletTestUtils.createToken());
|
||||
assertEquals(3, results.getAuthorities().length);
|
||||
assertEquals(new GrantedAuthorityImpl(ContainerPortletAuthoritiesPopulator.DEFAULT_USER_ROLE), results.getAuthorities()[0]);
|
||||
assertEquals(new GrantedAuthorityImpl(PortletTestUtils.TESTROLE1), results.getAuthorities()[1]);
|
||||
assertEquals(new GrantedAuthorityImpl(PortletTestUtils.TESTROLE2), results.getAuthorities()[2]);
|
||||
}
|
||||
|
||||
public void testGetGrantedAuthoritiesCustomPrefix() throws Exception {
|
||||
String prefix = "IHAVE_";
|
||||
ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator();
|
||||
populator.setRolesToCheck(createRolesToCheck());
|
||||
populator.setRolePrefix(prefix);
|
||||
UserDetails results = populator.getUserDetails(PortletTestUtils.createToken());
|
||||
assertEquals(3, results.getAuthorities().length);
|
||||
assertEquals(new GrantedAuthorityImpl(ContainerPortletAuthoritiesPopulator.DEFAULT_USER_ROLE), results.getAuthorities()[0]);
|
||||
assertEquals(new GrantedAuthorityImpl(prefix + PortletTestUtils.PORTALROLE1), results.getAuthorities()[1]);
|
||||
assertEquals(new GrantedAuthorityImpl(prefix + PortletTestUtils.PORTALROLE2), results.getAuthorities()[2]);
|
||||
}
|
||||
|
||||
public void testGetGrantedAuthoritiesNullDefault() throws Exception {
|
||||
ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator();
|
||||
populator.setUserRole(null);
|
||||
UserDetails results = populator.getUserDetails(PortletTestUtils.createToken());
|
||||
assertEquals(0, results.getAuthorities().length);
|
||||
}
|
||||
|
||||
public void testGetGrantedAuthoritiesEmptyDefault() throws Exception {
|
||||
ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator();
|
||||
populator.setUserRole("");
|
||||
UserDetails results = populator.getUserDetails(PortletTestUtils.createToken());
|
||||
assertEquals(0, results.getAuthorities().length);
|
||||
}
|
||||
|
||||
public void testGetGrantedAuthoritiesForInvalidToken() throws Exception {
|
||||
ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator();
|
||||
PortletAuthenticationToken token = PortletTestUtils.createToken();
|
||||
token.setDetails(null);
|
||||
try {
|
||||
populator.getUserDetails(token);
|
||||
fail("Should have thrown AuthenticationServiceException");
|
||||
} catch (AuthenticationServiceException e) {
|
||||
// ignore
|
||||
}
|
||||
token.setDetails("bogus");
|
||||
try {
|
||||
populator.getUserDetails(token);
|
||||
fail("Should have thrown AuthenticationServiceException");
|
||||
} catch (AuthenticationServiceException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.providers.portlet.populator;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
import org.acegisecurity.providers.portlet.PortletAuthenticationToken;
|
||||
import org.acegisecurity.providers.portlet.PortletTestUtils;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
import org.acegisecurity.userdetails.UserDetailsService;
|
||||
import org.acegisecurity.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
|
||||
/**
|
||||
* Tests for {@link DaoPortletAuthoritiesPopulator}
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class DaoPortletAuthoritiesPopulatorTests extends TestCase {
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public DaoPortletAuthoritiesPopulatorTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public DaoPortletAuthoritiesPopulatorTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testRequiresDao() throws Exception {
|
||||
DaoPortletAuthoritiesPopulator populator = new DaoPortletAuthoritiesPopulator();
|
||||
try {
|
||||
populator.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException failed) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetGrantedAuthoritiesForValidUser() throws Exception {
|
||||
DaoPortletAuthoritiesPopulator populator = new DaoPortletAuthoritiesPopulator();
|
||||
populator.setUserDetailsService(new MockAuthenticationDao());
|
||||
populator.afterPropertiesSet();
|
||||
UserDetails results = populator.getUserDetails(PortletTestUtils.createToken());
|
||||
assertEquals(2, results.getAuthorities().length);
|
||||
assertEquals(new GrantedAuthorityImpl(PortletTestUtils.TESTROLE1), results.getAuthorities()[0]);
|
||||
assertEquals(new GrantedAuthorityImpl(PortletTestUtils.TESTROLE2), results.getAuthorities()[1]);
|
||||
}
|
||||
|
||||
public void testGetGrantedAuthoritiesForInvalidUser() throws Exception {
|
||||
DaoPortletAuthoritiesPopulator populator = new DaoPortletAuthoritiesPopulator();
|
||||
populator.setUserDetailsService(new MockAuthenticationDao());
|
||||
populator.afterPropertiesSet();
|
||||
try {
|
||||
populator.getUserDetails(new PortletAuthenticationToken("dummy", "dummy", null));
|
||||
fail("Should have thrown UsernameNotFoundException");
|
||||
} catch (UsernameNotFoundException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class MockAuthenticationDao implements UserDetailsService {
|
||||
|
||||
public UserDetails loadUserByUsername(String username)
|
||||
throws UsernameNotFoundException, DataAccessException {
|
||||
if (PortletTestUtils.TESTUSER.equals(username))
|
||||
return PortletTestUtils.createUser();
|
||||
throw new UsernameNotFoundException("Could not find: " + username);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.ui.portlet;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.acegisecurity.BadCredentialsException;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
/**
|
||||
* Tests {@link PortletProcessingFilterEntryPoint}.
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class PortletProcessingFilterEntryPointTests extends TestCase {
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public PortletProcessingFilterEntryPointTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public PortletProcessingFilterEntryPointTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testNormalOperation() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
PortletProcessingFilterEntryPoint entryPoint = new PortletProcessingFilterEntryPoint();
|
||||
entryPoint.commence(request, response, new BadCredentialsException(null));
|
||||
assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus());
|
||||
}
|
||||
|
||||
}
|
||||
+284
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright 2005-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.acegisecurity.ui.portlet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.portlet.PortletRequest;
|
||||
import javax.portlet.PortletSession;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.AuthenticationManager;
|
||||
import org.acegisecurity.BadCredentialsException;
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
import org.acegisecurity.context.SecurityContextHolder;
|
||||
import org.acegisecurity.providers.TestingAuthenticationToken;
|
||||
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.acegisecurity.providers.portlet.PortletAuthenticationToken;
|
||||
import org.acegisecurity.providers.portlet.PortletTestUtils;
|
||||
import org.acegisecurity.ui.AbstractProcessingFilter;
|
||||
import org.acegisecurity.userdetails.User;
|
||||
import org.springframework.mock.web.portlet.MockActionRequest;
|
||||
import org.springframework.mock.web.portlet.MockActionResponse;
|
||||
import org.springframework.mock.web.portlet.MockRenderRequest;
|
||||
import org.springframework.mock.web.portlet.MockRenderResponse;
|
||||
|
||||
/**
|
||||
* Tests {@link PortletProcessingInterceptor}.
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
public class PortletProcessingInterceptorTests extends TestCase {
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public PortletProcessingInterceptorTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public PortletProcessingInterceptorTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
public void testRequiresAuthenticationManager() throws Exception {
|
||||
PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor();
|
||||
try {
|
||||
interceptor.afterPropertiesSet();
|
||||
fail("Expected IllegalArgumentException");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
public void testNormalRenderRequestProcessing() throws Exception {
|
||||
|
||||
// Build mock request and response
|
||||
MockRenderRequest request = PortletTestUtils.createRenderRequest();
|
||||
MockRenderResponse response = PortletTestUtils.createRenderResponse();
|
||||
|
||||
// Prepare interceptor
|
||||
PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor();
|
||||
interceptor.setAuthenticationManager(new MockPortletAuthenticationManager());
|
||||
interceptor.afterPropertiesSet();
|
||||
|
||||
// Execute preHandlerRender phase and verify results
|
||||
interceptor.preHandleRender(request, response, null);
|
||||
assertEquals(PortletTestUtils.createAuthenticatedToken(),
|
||||
SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
// Execute postHandlerRender phase and verify nothing changed
|
||||
interceptor.postHandleRender(request, response, null, null);
|
||||
assertEquals(PortletTestUtils.createAuthenticatedToken(),
|
||||
SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
// Execute afterRenderCompletion phase and verify nothing changed
|
||||
interceptor.afterRenderCompletion(request, response, null, null);
|
||||
assertEquals(PortletTestUtils.createAuthenticatedToken(),
|
||||
SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
public void testNormalActionRequestProcessing() throws Exception {
|
||||
|
||||
// Build mock request and response
|
||||
MockActionRequest request = PortletTestUtils.createActionRequest();
|
||||
MockActionResponse response = PortletTestUtils.createActionResponse();
|
||||
|
||||
// Prepare interceptor
|
||||
PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor();
|
||||
interceptor.setAuthenticationManager(new MockPortletAuthenticationManager());
|
||||
interceptor.afterPropertiesSet();
|
||||
|
||||
// Execute preHandlerAction phase and verify results
|
||||
interceptor.preHandleAction(request, response, null);
|
||||
assertEquals(PortletTestUtils.createAuthenticatedToken(),
|
||||
SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
// Execute afterActionCompletion phase and verify nothing changed
|
||||
interceptor.afterActionCompletion(request, response, null, null);
|
||||
assertEquals(PortletTestUtils.createAuthenticatedToken(),
|
||||
SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
public void testAuthenticationFailsWithNoCredentials()
|
||||
throws Exception {
|
||||
|
||||
// Build mock request and response
|
||||
MockActionRequest request = new MockActionRequest();
|
||||
MockActionResponse response = new MockActionResponse();
|
||||
|
||||
// Prepare and execute interceptor
|
||||
PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor();
|
||||
interceptor.setAuthenticationManager(new MockPortletAuthenticationManager());
|
||||
interceptor.afterPropertiesSet();
|
||||
interceptor.preHandleAction(request, response, null);
|
||||
|
||||
// Verify that authentication is empty
|
||||
assertNull(SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
// Verify that proper exception was thrown
|
||||
assertTrue(request.getPortletSession().getAttribute(
|
||||
AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY,
|
||||
PortletSession.APPLICATION_SCOPE)
|
||||
instanceof BadCredentialsException);
|
||||
}
|
||||
|
||||
public void testExistingAuthenticationIsLeftAlone() throws Exception {
|
||||
|
||||
// Build mock request and response
|
||||
MockActionRequest request = PortletTestUtils.createActionRequest();
|
||||
MockActionResponse response = PortletTestUtils.createActionResponse();
|
||||
|
||||
// Prepare interceptor
|
||||
PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor();
|
||||
interceptor.setAuthenticationManager(new MockPortletAuthenticationManager());
|
||||
interceptor.afterPropertiesSet();
|
||||
|
||||
UsernamePasswordAuthenticationToken testingToken = new UsernamePasswordAuthenticationToken("dummy", "dummy", null);
|
||||
UsernamePasswordAuthenticationToken baselineToken = new UsernamePasswordAuthenticationToken("dummy", "dummy", null);
|
||||
SecurityContextHolder.getContext().setAuthentication(testingToken);
|
||||
|
||||
// Execute preHandlerAction phase and verify results
|
||||
interceptor.preHandleAction(request, response, null);
|
||||
assertTrue(SecurityContextHolder.getContext().getAuthentication() == testingToken);
|
||||
assertEquals(baselineToken, SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
// Execute afterActionCompletion phase and verify nothing changed
|
||||
interceptor.afterActionCompletion(request, response, null, null);
|
||||
assertTrue(SecurityContextHolder.getContext().getAuthentication() == testingToken);
|
||||
assertEquals(baselineToken, SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
public void testUsernameFromRemoteUser() throws Exception {
|
||||
|
||||
// Build mock request and response
|
||||
MockActionRequest request = new MockActionRequest();
|
||||
MockActionResponse response = new MockActionResponse();
|
||||
request.setRemoteUser(PortletTestUtils.TESTUSER);
|
||||
request.setAuthType(PortletRequest.FORM_AUTH);
|
||||
|
||||
// Prepare and execute interceptor
|
||||
PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor();
|
||||
interceptor.setAuthenticationManager(new MockPortletAuthenticationManager());
|
||||
interceptor.afterPropertiesSet();
|
||||
interceptor.preHandleAction(request, response, null);
|
||||
|
||||
// Verify username
|
||||
assertEquals(PortletTestUtils.TESTUSER,
|
||||
SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
}
|
||||
|
||||
public void testUsernameFromPrincipal() throws Exception {
|
||||
|
||||
// Build mock request and response
|
||||
MockActionRequest request = new MockActionRequest();
|
||||
MockActionResponse response = new MockActionResponse();
|
||||
request.setUserPrincipal(new TestingAuthenticationToken(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, null));
|
||||
request.setAuthType(PortletRequest.FORM_AUTH);
|
||||
|
||||
// Prepare and execute interceptor
|
||||
PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor();
|
||||
interceptor.setAuthenticationManager(new MockPortletAuthenticationManager());
|
||||
interceptor.afterPropertiesSet();
|
||||
interceptor.preHandleAction(request, response, null);
|
||||
|
||||
// Verify username
|
||||
assertEquals(PortletTestUtils.TESTUSER,
|
||||
SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
}
|
||||
|
||||
public void testUsernameFromUserInfo() throws Exception {
|
||||
|
||||
// Build mock request and response
|
||||
MockActionRequest request = new MockActionRequest();
|
||||
MockActionResponse response = new MockActionResponse();
|
||||
HashMap userInfo = new HashMap();
|
||||
userInfo.put("user.name.given", "Test");
|
||||
userInfo.put("user.name.family", "User");
|
||||
userInfo.put("user.id", "mytestuser");
|
||||
request.setAttribute(PortletRequest.USER_INFO, userInfo);
|
||||
request.setAuthType(PortletRequest.FORM_AUTH);
|
||||
|
||||
// Prepare and execute interceptor
|
||||
PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor();
|
||||
interceptor.setAuthenticationManager(new MockPortletAuthenticationManager());
|
||||
ArrayList userNameAttributes = new ArrayList();
|
||||
userNameAttributes.add("user.name");
|
||||
userNameAttributes.add("user.id");
|
||||
interceptor.setUserNameAttributes(userNameAttributes);
|
||||
interceptor.afterPropertiesSet();
|
||||
interceptor.preHandleAction(request, response, null);
|
||||
|
||||
// Verify username
|
||||
assertEquals("mytestuser", SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private static class MockPortletAuthenticationManager implements AuthenticationManager {
|
||||
|
||||
public Authentication authenticate(Authentication token) {
|
||||
|
||||
// Make sure we got a valid token
|
||||
if (!(token instanceof PortletAuthenticationToken)) {
|
||||
TestCase.fail("Expected PortletAuthentication object-- got: " + token);
|
||||
}
|
||||
|
||||
// Make sure the token details are the PortletRequest
|
||||
if (!(token.getDetails() instanceof PortletRequest)) {
|
||||
TestCase.fail("Expected Authentication.getDetails to be a PortletRequest object -- got: " + token.getDetails());
|
||||
}
|
||||
|
||||
// Make sure it's got a principal
|
||||
if (token.getPrincipal() == null) {
|
||||
throw new BadCredentialsException("Mock authentication manager rejecting null principal");
|
||||
}
|
||||
|
||||
// Make sure it's got credentials
|
||||
if (token.getCredentials() == null) {
|
||||
throw new BadCredentialsException("Mock authentication manager rejecting null credentials");
|
||||
}
|
||||
|
||||
// create resulting Authentication object
|
||||
User user = new User(token.getName(), token.getCredentials().toString(), true, true, true, true,
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl(PortletTestUtils.TESTROLE1), new GrantedAuthorityImpl(PortletTestUtils.TESTROLE2)});
|
||||
PortletAuthenticationToken result = new PortletAuthenticationToken(
|
||||
user, user.getPassword(), user.getAuthorities());
|
||||
result.setAuthenticated(true);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user