diff --git a/core/src/main/java/org/springframework/security/authoritymapping/SimpleMappableAttributesRetriever.java b/core/src/main/java/org/springframework/security/authoritymapping/SimpleMappableAttributesRetriever.java
index ec205ea36a..d1d6543c68 100755
--- a/core/src/main/java/org/springframework/security/authoritymapping/SimpleMappableAttributesRetriever.java
+++ b/core/src/main/java/org/springframework/security/authoritymapping/SimpleMappableAttributesRetriever.java
@@ -1,6 +1,5 @@
package org.springframework.security.authoritymapping;
-import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@@ -25,9 +24,10 @@ public class SimpleMappableAttributesRetriever implements MappableAttributesRetr
return mappableAttributes;
}
- public void setMappableAttributes(String[] aMappableRoles) {
- mappableAttributes = new HashSet This interceptor populates the {@link SecurityContextHolder} with information obtained from the
- * The If a valid A If for whatever reason no This interceptor must be executed beforePortletSession. It is applied to both ActionRequests and
- * RenderRequestsPortletSession will be queried to retrieve the SecurityContext that should
- * be stored against the SecurityContextHolder for the duration of the portlet request. At the
- * end of the request, any updates made to the SecurityContextHolder will be persisted back to the
- * PortletSession by this interceptor.SecurityContext cannot be obtained from the PortletSession for
- * whatever reason, a fresh SecurityContext 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.springframework.security.context.SecurityContextImpl}. PortletSession may be created by this interceptor if one does not already exist. If at the
- * end of the portlet request the PortletSession does not exist, one will only be created if
- * the current contents of the SecurityContextHolder are not the {@link java.lang.Object#equals}
- * to a new instance of {@link #context}. This avoids needless PortletSession creation,
- * and automates the storage of changes made to the SecurityContextHolder. There is one exception to
- * this rule, that is if the {@link #forceEagerSessionCreation} property is true, in which case
- * sessions will always be created irrespective of normal session-minimization logic (the default is
- * false, as this is resource intensive and not recommended).PortletSession should ever be created, the
- * {@link #allowSessionCreation} property should be set to false. Only do this if you really need
- * to conserve server memory and ensure all classes using the SecurityContextHolder are designed to
- * have no persistence of the SecurityContext between web requests. Please note that if
- * {@link #forceEagerSessionCreation} is true, the allowSessionCreation must also be
- * true (setting it to false will cause a startup-time error).SecurityContextHolder to contain a valid SecurityContext by the time they execute.
An important nuance to this interceptor is that (by default) the SecurityContext is stored
- * into the APPLICATION_SCOPE of the PortletSession. 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 SecurityContext 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 SecurityContext
- * object from the session. This allows these calls to be secured as well as the portlet calls.
Unlike HttpSessionContextIntegrationFilter, 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.
PortletSession if
- * needed (sessions are always created sparingly, but setting this value to
- * false will prohibit sessions from ever being created).
- * Defaults to true. Do not set to false if
- * you are have set {@link #forceEagerSessionCreation} to true,
- * as the properties would be in conflict.
- */
- private boolean allowSessionCreation = true;
-
- /**
- * Indicates if this interceptor is required to create a PortletSession
- * for every request before proceeding through the request process, even if the
- * PortletSession would not ordinarily have been created. By
- * default this is false, which is entirely appropriate for
- * most circumstances as you do not want a PortletSession
- * created unless the interceptor actually needs one. It is envisaged the main
- * situation in which this property would be set to true is
- * if using other interceptors that depend on a PortletSession
- * already existing. This is only required in specialized cases, so leave it set to
- * false unless you have an actual requirement and aware of the
- * session creation overhead.
- */
- private boolean forceEagerSessionCreation = false;
-
- /**
- * Indicates whether the SecurityContext will be cloned from
- * the PortletSession. The default is to simply reference
- * (the default is false). 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
- * PortletSession. 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 PortletSession. For unusual cases where this is not
- * permitted, change this value to true and ensure the
- * {@link #context} is set to a SecurityContext that
- * implements {@link Cloneable} and overrides the clone()
- * method.
- */
- private boolean cloneFromPortletSession = false;
-
- /**
- * Indicates wether the APPLICATION_SCOPE mode of the
- * PortletSession should be used for storing the
- * SecurityContext. The default is true.
- * 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
- * false, then the PORTLET_SCOPE 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.springframework.security.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(SPRING_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 SPRING_SECURITY_CONTEXT a valid SecurityContext and "
- + "set to SecurityContextHolder: '" + contextFromSessionObject + "'");
- SecurityContextHolder.setContext((SecurityContext) contextFromSessionObject);
- } else {
- if (logger.isWarnEnabled())
- logger.warn("SPRING_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 SPRING_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(SPRING_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 SecurityContext object. The specific class is
- * determined by the setting of the {@link #context} property.
- * @return the new SecurityContext
- * @throws PortletException if the creation throws an InstantiationException or
- * an IllegalAccessException, then this method will wrap them in a
- * PortletException
- */
- 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;
- }
-
-}
+/*
+ * 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.springframework.security.context;
+
+import java.lang.reflect.Method;
+
+import javax.portlet.*;
+
+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;
+import org.springframework.security.web.context.SecurityContextPersistenceFilter;
+import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
+
+/**
+ * This interceptor populates the {@link SecurityContextHolder} with information obtained from the
+ * PortletSession. It is applied to both ActionRequests and
+ * RenderRequests
The PortletSession will be queried to retrieve the SecurityContext that should
+ * be stored against the SecurityContextHolder for the duration of the portlet request. At the
+ * end of the request, any updates made to the SecurityContextHolder will be persisted back to the
+ * PortletSession by this interceptor.
If a valid SecurityContext cannot be obtained from the PortletSession for
+ * whatever reason, a fresh SecurityContext 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.springframework.security.context.SecurityContextImpl}.
A PortletSession may be created by this interceptor if one does not already exist. If at the
+ * end of the portlet request the PortletSession does not exist, one will only be created if
+ * the current contents of the SecurityContextHolder are not the {@link java.lang.Object#equals}
+ * to a new instance of {@link #context}. This avoids needless PortletSession creation,
+ * and automates the storage of changes made to the SecurityContextHolder. There is one exception to
+ * this rule, that is if the {@link #forceEagerSessionCreation} property is true, in which case
+ * sessions will always be created irrespective of normal session-minimization logic (the default is
+ * false, as this is resource intensive and not recommended).
If for whatever reason no PortletSession should ever be created, the
+ * {@link #allowSessionCreation} property should be set to false. Only do this if you really need
+ * to conserve server memory and ensure all classes using the SecurityContextHolder are designed to
+ * have no persistence of the SecurityContext between web requests. Please note that if
+ * {@link #forceEagerSessionCreation} is true, the allowSessionCreation must also be
+ * true (setting it to false will cause a startup-time error).
This interceptor must be executed before
any authentication processing mechanisms. These + * mechanisms (specifically {@link org.springframework.security.ui.portlet.PortletProcessingInterceptor}) expect the + *SecurityContextHolder to contain a valid SecurityContext by the time they execute.
+ *
+ * An important nuance to this interceptor is that (by default) the SecurityContext is stored
+ * into the APPLICATION_SCOPE of the PortletSession. 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 SecurityContext 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 SecurityContextPersistenceFilter} to access the same SecurityContext
+ * object from the session. This allows these calls to be secured as well as the portlet calls.
Unlike HttpSessionContextIntegrationFilter, 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.
PortletSession if
+ * needed (sessions are always created sparingly, but setting this value to
+ * false will prohibit sessions from ever being created).
+ * Defaults to true. Do not set to false if
+ * you are have set {@link #forceEagerSessionCreation} to true,
+ * as the properties would be in conflict.
+ */
+ private boolean allowSessionCreation = true;
+
+ /**
+ * Indicates if this interceptor is required to create a PortletSession
+ * for every request before proceeding through the request process, even if the
+ * PortletSession would not ordinarily have been created. By
+ * default this is false, which is entirely appropriate for
+ * most circumstances as you do not want a PortletSession
+ * created unless the interceptor actually needs one. It is envisaged the main
+ * situation in which this property would be set to true is
+ * if using other interceptors that depend on a PortletSession
+ * already existing. This is only required in specialized cases, so leave it set to
+ * false unless you have an actual requirement and aware of the
+ * session creation overhead.
+ */
+ private boolean forceEagerSessionCreation = false;
+
+ /**
+ * Indicates whether the SecurityContext will be cloned from
+ * the PortletSession. The default is to simply reference
+ * (the default is false). 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
+ * PortletSession. 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 PortletSession. For unusual cases where this is not
+ * permitted, change this value to true and ensure the
+ * {@link #context} is set to a SecurityContext that
+ * implements {@link Cloneable} and overrides the clone()
+ * method.
+ */
+ private boolean cloneFromPortletSession = false;
+
+ /**
+ * Indicates wether the APPLICATION_SCOPE mode of the
+ * PortletSession should be used for storing the
+ * SecurityContext. The default is true.
+ * 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
+ * false, then the PORTLET_SCOPE 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.springframework.security.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);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean preHandleResource(ResourceRequest request, ResourceResponse response, Object handler) throws Exception {
+ return preHandle(request, response, handler);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void postHandleResource(ResourceRequest request, ResourceResponse response, Object handler, ModelAndView modelAndView) throws Exception {
+ // no-op
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void afterResourceCompletion(ResourceRequest request, ResourceResponse response, Object handler, Exception ex) throws Exception {
+ // call to common afterCompletion method
+ afterCompletion(request, response, handler, ex);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean preHandleEvent(EventRequest request, EventResponse response, Object handler) throws Exception {
+ return preHandle(request, response, handler);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void afterEventCompletion(EventRequest request, EventResponse 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(SPRING_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 SPRING_SECURITY_CONTEXT a valid SecurityContext and "
+ + "set to SecurityContextHolder: '" + contextFromSessionObject + "'");
+ SecurityContextHolder.setContext((SecurityContext) contextFromSessionObject);
+ } else {
+ if (logger.isWarnEnabled())
+ logger.warn("SPRING_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 SPRING_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(SPRING_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 SecurityContext object. The specific class is
+ * determined by the setting of the {@link #context} property.
+ * @return the new SecurityContext
+ * @throws PortletException if the creation throws an InstantiationException or
+ * an IllegalAccessException, then this method will wrap them in a
+ * PortletException
+ */
+ 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;
+ }
+
+}
diff --git a/portlet/src/main/java/org/springframework/security/ui/portlet/PortletPreAuthenticatedAuthenticationDetailsSource.java b/portlet/src/main/java/org/springframework/security/ui/portlet/PortletPreAuthenticatedAuthenticationDetailsSource.java
index 8989a70a3b..59a1ccac89 100644
--- a/portlet/src/main/java/org/springframework/security/ui/portlet/PortletPreAuthenticatedAuthenticationDetailsSource.java
+++ b/portlet/src/main/java/org/springframework/security/ui/portlet/PortletPreAuthenticatedAuthenticationDetailsSource.java
@@ -6,7 +6,7 @@ import java.util.Set;
import javax.portlet.PortletRequest;
-import org.springframework.security.ui.preauth.j2ee.AbstractPreAuthenticatedAuthenticationDetailsSource;
+import org.springframework.security.web.authentication.preauth.j2ee.AbstractPreAuthenticatedAuthenticationDetailsSource;
public class PortletPreAuthenticatedAuthenticationDetailsSource extends AbstractPreAuthenticatedAuthenticationDetailsSource {
diff --git a/portlet/src/main/java/org/springframework/security/ui/portlet/PortletProcessingInterceptor.java b/portlet/src/main/java/org/springframework/security/ui/portlet/PortletProcessingInterceptor.java
index 5916fc6c2b..3b82be693e 100644
--- a/portlet/src/main/java/org/springframework/security/ui/portlet/PortletProcessingInterceptor.java
+++ b/portlet/src/main/java/org/springframework/security/ui/portlet/PortletProcessingInterceptor.java
@@ -1,322 +1,342 @@
-/*
- * 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.springframework.security.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.springframework.security.Authentication;
-import org.springframework.security.AuthenticationDetailsSource;
-import org.springframework.security.AuthenticationDetailsSourceImpl;
-import org.springframework.security.AuthenticationException;
-import org.springframework.security.AuthenticationManager;
-import org.springframework.security.context.SecurityContext;
-import org.springframework.security.context.SecurityContextHolder;
-import org.springframework.security.providers.preauth.PreAuthenticatedAuthenticationToken;
-import org.springframework.security.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;
-
-/**
- * This interceptor is responsible for processing portlet authentication requests. This
- * is the portlet equivalent of the AuthenticationProcessingFilter used for
- * traditional servlet-based web applications. It is applied to both ActionRequests
- * and RenderRequests alike. If authentication is successful, the resulting
- * {@link Authentication} object will be placed into the SecurityContext, which
- * is guaranteed to have already been created by an earlier interceptor. If authentication
- * fails, the AuthenticationException will be placed into the
- * APPLICATION_SCOPE of the PortletSession with the attribute defined
- * by {@link AbstractProcessingFilter#SPRING_SECURITY_LAST_EXCEPTION_KEY}.
Some portals do not properly provide the identity of the current user via the
- * getRemoteUser() or getUserPrincipal() methods of the
- * PortletRequest. In these cases they sometimes make it available in the
- * USER_INFO map provided as one of the attributes of the request. If this is
- * the case in your portal, you can specify a list of USER_INFO attributes
- * to check for the username via the userNameAttributes 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.
This interceptor will put the PortletRequest object into the
- * details property of the Authentication object that is sent
- * as a request to the AuthenticationManager. 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 USER_INFO map in the resulting Authentication
- * object.
PortletRequest should return the name
- * of the user in the getRemoteUser() method. It should also provide a
- * java.security.Principal object from the getUserPrincipal()
- * method. We will first try these to come up with a valid username.
- * Unfortunately, some portals do not properly return these values for authenticated
- * users. So, if neither of those succeeds and if the userNameAttributes
- * property has been populated, then we will search through the USER_INFO
- * map from the request to see if we can find a valid username.
- * This method can be overridden by subclasses to provide special handling
- * for portals with weak support for the JSR 168 spec.
- * @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.
- * 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.
- * @param request the portlet request object
- * @return the determined credentials object, or null if none found
- */
- protected Object getCredentialsFromRequest(PortletRequest request) {
- if (useAuthTypeAsCredentials) {
- return request.getAuthType();
- }
-
- return "dummy";
- }
-
- /**
- * 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 void setAuthenticationManager(AuthenticationManager authenticationManager) {
- this.authenticationManager = authenticationManager;
- }
-
- public void setUserNameAttributes(List userNameAttributes) {
- this.userNameAttributes = userNameAttributes;
- }
-
- public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
- this.authenticationDetailsSource = authenticationDetailsSource;
- }
-
- /**
- * It true, the "authType" proerty of the PortletRequest will be used as the credentials.
- * Defaults to false.
- *
- * @param useAuthTypeAsCredentials
- */
- public void setUseAuthTypeAsCredentials(boolean useAuthTypeAsCredentials) {
- this.useAuthTypeAsCredentials = useAuthTypeAsCredentials;
- }
-}
+/*
+ * 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.springframework.security.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.*;
+
+import org.springframework.security.Authentication;
+import org.springframework.security.AuthenticationDetailsSource;
+import org.springframework.security.AuthenticationDetailsSourceImpl;
+import org.springframework.security.AuthenticationException;
+import org.springframework.security.AuthenticationManager;
+import org.springframework.security.web.authentication.AbstractProcessingFilter;
+import org.springframework.security.context.SecurityContext;
+import org.springframework.security.context.SecurityContextHolder;
+import org.springframework.security.providers.preauth.PreAuthenticatedAuthenticationToken;
+import org.springframework.security.web.authentication.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;
+
+/**
+ * This interceptor is responsible for processing portlet authentication requests. This
+ * is the portlet equivalent of the AuthenticationProcessingFilter used for
+ * traditional servlet-based web applications. It is applied to both ActionRequests
+ * and RenderRequests alike. If authentication is successful, the resulting
+ * {@link Authentication} object will be placed into the SecurityContext, which
+ * is guaranteed to have already been created by an earlier interceptor. If authentication
+ * fails, the AuthenticationException will be placed into the
+ * APPLICATION_SCOPE of the PortletSession with the attribute defined
+ * by {@link AbstractProcessingFilter#SPRING_SECURITY_LAST_EXCEPTION_KEY}.
+ *
+ * Some portals do not properly provide the identity of the current user via the
+ * getRemoteUser() or getUserPrincipal() methods of the
+ * PortletRequest. In these cases they sometimes make it available in the
+ * USER_INFO map provided as one of the attributes of the request. If this is
+ * the case in your portal, you can specify a list of USER_INFO attributes
+ * to check for the username via the userNameAttributes 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.
+ *
+ * This interceptor will put the PortletRequest object into the
+ * details property of the Authentication object that is sent
+ * as a request to the AuthenticationManager.
+ *
+ * @see org.springframework.security.web.authentication.AbstractProcessingFilter
+ * @see org.springframework.security.web.authentication.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;
+
+ private AuthenticationDetailsSource authenticationDetailsSource;
+
+ private boolean useAuthTypeAsCredentials = false;
+
+ public PortletProcessingInterceptor() {
+ authenticationDetailsSource = new AuthenticationDetailsSourceImpl();
+ ((AuthenticationDetailsSourceImpl)authenticationDetailsSource).setClazz(PortletAuthenticationDetails.class);
+ }
+
+ //~ 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 {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean preHandleResource(ResourceRequest request, ResourceResponse response, Object handler) throws Exception {
+ return preHandle(request, response, handler);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void postHandleResource(ResourceRequest request, ResourceResponse response, Object handler, ModelAndView modelAndView) throws Exception {
+ }
+
+ public void afterResourceCompletion(ResourceRequest request, ResourceResponse response, Object handler, Exception ex) throws Exception {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean preHandleEvent(EventRequest request, EventResponse response, Object handler) throws Exception {
+ return preHandle(request, response, handler);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void afterEventCompletion(EventRequest request, EventResponse 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
+ PreAuthenticatedAuthenticationToken authRequest = new PreAuthenticatedAuthenticationToken(
+ getPrincipalFromRequest(request),
+ getCredentialsFromRequest(request));
+
+ // put the PortletRequest into the authentication request as the "details"
+ authRequest.setDetails(authenticationDetailsSource.buildDetails(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", failed);
+ }
+ ctx.setAuthentication(null);
+ request.getPortletSession().setAttribute(
+ AbstractProcessingFilter.SPRING_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 PortletRequest should return the name
+ * of the user in the getRemoteUser() method. It should also provide a
+ * java.security.Principal object from the getUserPrincipal()
+ * method. We will first try these to come up with a valid username.
+ * Unfortunately, some portals do not properly return these values for authenticated
+ * users. So, if neither of those succeeds and if the userNameAttributes
+ * property has been populated, then we will search through the USER_INFO
+ * map from the request to see if we can find a valid username.
+ * This method can be overridden by subclasses to provide special handling
+ * for portals with weak support for the JSR 168 spec.
+ * @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.
+ * 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.
+ * @param request the portlet request object
+ * @return the determined credentials object, or null if none found
+ */
+ protected Object getCredentialsFromRequest(PortletRequest request) {
+ if (useAuthTypeAsCredentials) {
+ return request.getAuthType();
+ }
+
+ return "dummy";
+ }
+
+ /**
+ * 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 void setAuthenticationManager(AuthenticationManager authenticationManager) {
+ this.authenticationManager = authenticationManager;
+ }
+
+ public void setUserNameAttributes(List userNameAttributes) {
+ this.userNameAttributes = userNameAttributes;
+ }
+
+ public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
+ this.authenticationDetailsSource = authenticationDetailsSource;
+ }
+
+ /**
+ * It true, the "authType" proerty of the PortletRequest will be used as the credentials.
+ * Defaults to false.
+ *
+ * @param useAuthTypeAsCredentials
+ */
+ public void setUseAuthTypeAsCredentials(boolean useAuthTypeAsCredentials) {
+ this.useAuthTypeAsCredentials = useAuthTypeAsCredentials;
+ }
+}
diff --git a/portlet/src/test/java/org/springframework/security/ui/portlet/PortletProcessingInterceptorTests.java b/portlet/src/test/java/org/springframework/security/ui/portlet/PortletProcessingInterceptorTests.java
index 42ca2cdaa2..b73223f490 100644
--- a/portlet/src/test/java/org/springframework/security/ui/portlet/PortletProcessingInterceptorTests.java
+++ b/portlet/src/test/java/org/springframework/security/ui/portlet/PortletProcessingInterceptorTests.java
@@ -34,6 +34,7 @@ import org.springframework.mock.web.portlet.MockRenderResponse;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationManager;
import org.springframework.security.BadCredentialsException;
+import org.springframework.security.web.authentication.AbstractProcessingFilter;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.TestingAuthenticationToken;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
diff --git a/samples/pom.xml b/samples/pom.xml
index f251960cf1..66aafd7952 100644
--- a/samples/pom.xml
+++ b/samples/pom.xml
@@ -16,7 +16,7 @@
preauth
openid
ldap
-
+ portlet
cas
diff --git a/samples/portlet/src/main/java/org/springframework/web/portlet/sample/SecurityContextPortlet.java b/samples/portlet/src/main/java/org/springframework/web/portlet/sample/SecurityContextPortlet.java
index 8f387cbec8..9f58890c46 100644
--- a/samples/portlet/src/main/java/org/springframework/web/portlet/sample/SecurityContextPortlet.java
+++ b/samples/portlet/src/main/java/org/springframework/web/portlet/sample/SecurityContextPortlet.java
@@ -11,11 +11,11 @@ import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import org.springframework.security.context.SecurityContextHolder;
-import org.springframework.security.ui.AbstractProcessingFilter;
+import org.springframework.security.web.authentication.AbstractProcessingFilter;
/**
- * A simple portlet which prints out the contents of the current {@link SecurityContext}
+ * A simple portlet which prints out the contents of the current {@link org.springframework.security.context.SecurityContext}
*
* @author Luke Taylor
*/
diff --git a/samples/portlet/src/main/resources/portlet/securityContextPortlet.xml b/samples/portlet/src/main/resources/portlet/securityContextPortlet.xml
index 4394b99c2e..a8e0a36812 100644
--- a/samples/portlet/src/main/resources/portlet/securityContextPortlet.xml
+++ b/samples/portlet/src/main/resources/portlet/securityContextPortlet.xml
@@ -38,7 +38,7 @@
-
+
tomcat
admin
manager
@@ -47,7 +47,7 @@
Guest
User
Power User
-
+
diff --git a/web/src/test/java/org/springframework/security/web/authentication/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSourceTests.java b/web/src/test/java/org/springframework/security/web/authentication/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSourceTests.java
index 2dbbe1ef0b..873eb1208f 100755
--- a/web/src/test/java/org/springframework/security/web/authentication/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSourceTests.java
+++ b/web/src/test/java/org/springframework/security/web/authentication/preauth/j2ee/J2eeBasedPreAuthenticatedWebAuthenticationDetailsSourceTests.java
@@ -1,150 +1,151 @@
-package org.springframework.security.web.authentication.preauth.j2ee;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.servlet.http.HttpServletRequest;
-
-import junit.framework.TestCase;
-
-import org.springframework.security.authoritymapping.MappableAttributesRetriever;
-import org.springframework.security.authoritymapping.Attributes2GrantedAuthoritiesMapper;
-import org.springframework.security.authoritymapping.SimpleMappableAttributesRetriever;
-import org.springframework.security.authoritymapping.SimpleAttributes2GrantedAuthoritiesMapper;
-import org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails;
-import org.springframework.security.web.authentication.preauth.j2ee.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource;
-import org.springframework.security.GrantedAuthority;
-
-import org.springframework.mock.web.MockHttpServletRequest;
-
-/**
- *
- * @author TSARDD
- */
-public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSourceTests extends TestCase {
-
- public final void testAfterPropertiesSetException() {
- J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource t = new J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource();
- try {
- t.afterPropertiesSet();
- fail("AfterPropertiesSet didn't throw expected exception");
- } catch (IllegalArgumentException expected) {
- } catch (Exception unexpected) {
- fail("AfterPropertiesSet throws unexpected exception");
- }
- }
-
- public final void testBuildDetailsHttpServletRequestNoMappedNoUserRoles() {
- String[] mappedRoles = new String[] {};
- String[] roles = new String[] {};
- String[] expectedRoles = new String[] {};
- testDetails(mappedRoles, roles, expectedRoles);
- }
-
- public final void testBuildDetailsHttpServletRequestNoMappedUnmappedUserRoles() {
- String[] mappedRoles = new String[] {};
- String[] roles = new String[] { "Role1", "Role2" };
- String[] expectedRoles = new String[] {};
- testDetails(mappedRoles, roles, expectedRoles);
- }
-
- public final void testBuildDetailsHttpServletRequestNoUserRoles() {
- String[] mappedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
- String[] roles = new String[] {};
- String[] expectedRoles = new String[] {};
- testDetails(mappedRoles, roles, expectedRoles);
- }
-
- public final void testBuildDetailsHttpServletRequestAllUserRoles() {
- String[] mappedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
- String[] roles = new String[] { "Role1", "Role2", "Role3", "Role4" };
- String[] expectedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
- testDetails(mappedRoles, roles, expectedRoles);
- }
-
- public final void testBuildDetailsHttpServletRequestUnmappedUserRoles() {
- String[] mappedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
- String[] roles = new String[] { "Role1", "Role2", "Role3", "Role4", "Role5" };
- String[] expectedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
- testDetails(mappedRoles, roles, expectedRoles);
- }
-
- public final void testBuildDetailsHttpServletRequestPartialUserRoles() {
- String[] mappedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
- String[] roles = new String[] { "Role2", "Role3" };
- String[] expectedRoles = new String[] { "Role2", "Role3" };
- testDetails(mappedRoles, roles, expectedRoles);
- }
-
- public final void testBuildDetailsHttpServletRequestPartialAndUnmappedUserRoles() {
- String[] mappedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
- String[] roles = new String[] { "Role2", "Role3", "Role5" };
- String[] expectedRoles = new String[] { "Role2", "Role3" };
- testDetails(mappedRoles, roles, expectedRoles);
- }
-
- private void testDetails(String[] mappedRoles, String[] userRoles, String[] expectedRoles) {
- J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource src = getJ2eeBasedPreAuthenticatedWebAuthenticationDetailsSource(mappedRoles);
- Object o = src.buildDetails(getRequest("testUser", userRoles));
- assertNotNull(o);
- assertTrue("Returned object not of type PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails, actual type: " + o.getClass(),
- o instanceof PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails);
- PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails details = (PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails) o;
- List gas = details.getGrantedAuthorities();
- assertNotNull("Granted authorities should not be null", gas);
- assertEquals(expectedRoles.length, gas.size());
-
- Collection expectedRolesColl = Arrays.asList(expectedRoles);
- Collection gasRolesSet = new HashSet();
- for (int i = 0; i < gas.size(); i++) {
- gasRolesSet.add(gas.get(i).getAuthority());
- }
- assertTrue("Granted Authorities do not match expected roles", expectedRolesColl.containsAll(gasRolesSet)
- && gasRolesSet.containsAll(expectedRolesColl));
- }
-
- private final J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource getJ2eeBasedPreAuthenticatedWebAuthenticationDetailsSource(
- String[] mappedRoles) {
- J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource result = new J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource();
- result.setMappableRolesRetriever(getMappableRolesRetriever(mappedRoles));
- result.setUserRoles2GrantedAuthoritiesMapper(getJ2eeUserRoles2GrantedAuthoritiesMapper());
- result.setClazz(PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.class);
-
- try {
- result.afterPropertiesSet();
- } catch (Exception expected) {
- fail("AfterPropertiesSet throws unexpected exception");
- }
- return result;
- }
-
- private MappableAttributesRetriever getMappableRolesRetriever(String[] mappedRoles) {
- SimpleMappableAttributesRetriever result = new SimpleMappableAttributesRetriever();
- result.setMappableAttributes(mappedRoles);
- return result;
- }
-
- private Attributes2GrantedAuthoritiesMapper getJ2eeUserRoles2GrantedAuthoritiesMapper() {
- SimpleAttributes2GrantedAuthoritiesMapper result = new SimpleAttributes2GrantedAuthoritiesMapper();
- result.setAddPrefixIfAlreadyExisting(false);
- result.setConvertAttributeToLowerCase(false);
- result.setConvertAttributeToUpperCase(false);
- result.setAttributePrefix("");
- return result;
- }
-
- private final HttpServletRequest getRequest(final String userName,final String[] aRoles)
- {
- MockHttpServletRequest req = new MockHttpServletRequest() {
- private Set roles = new HashSet(Arrays.asList(aRoles));
- public boolean isUserInRole(String arg0) {
- return roles.contains(arg0);
- }
- };
- req.setRemoteUser(userName);
- return req;
- }
-}
+package org.springframework.security.web.authentication.preauth.j2ee;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+
+import junit.framework.TestCase;
+
+import org.springframework.security.authoritymapping.MappableAttributesRetriever;
+import org.springframework.security.authoritymapping.Attributes2GrantedAuthoritiesMapper;
+import org.springframework.security.authoritymapping.SimpleMappableAttributesRetriever;
+import org.springframework.security.authoritymapping.SimpleAttributes2GrantedAuthoritiesMapper;
+import org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails;
+import org.springframework.security.web.authentication.preauth.j2ee.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource;
+import org.springframework.security.GrantedAuthority;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.util.StringUtils;
+
+/**
+ *
+ * @author TSARDD
+ */
+public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSourceTests extends TestCase {
+
+ public final void testAfterPropertiesSetException() {
+ J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource t = new J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource();
+ try {
+ t.afterPropertiesSet();
+ fail("AfterPropertiesSet didn't throw expected exception");
+ } catch (IllegalArgumentException expected) {
+ } catch (Exception unexpected) {
+ fail("AfterPropertiesSet throws unexpected exception");
+ }
+ }
+
+ public final void testBuildDetailsHttpServletRequestNoMappedNoUserRoles() {
+ String[] mappedRoles = new String[] {};
+ String[] roles = new String[] {};
+ String[] expectedRoles = new String[] {};
+ testDetails(mappedRoles, roles, expectedRoles);
+ }
+
+ public final void testBuildDetailsHttpServletRequestNoMappedUnmappedUserRoles() {
+ String[] mappedRoles = new String[] {};
+ String[] roles = new String[] { "Role1", "Role2" };
+ String[] expectedRoles = new String[] {};
+ testDetails(mappedRoles, roles, expectedRoles);
+ }
+
+ public final void testBuildDetailsHttpServletRequestNoUserRoles() {
+ String[] mappedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
+ String[] roles = new String[] {};
+ String[] expectedRoles = new String[] {};
+ testDetails(mappedRoles, roles, expectedRoles);
+ }
+
+ public final void testBuildDetailsHttpServletRequestAllUserRoles() {
+ String[] mappedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
+ String[] roles = new String[] { "Role1", "Role2", "Role3", "Role4" };
+ String[] expectedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
+ testDetails(mappedRoles, roles, expectedRoles);
+ }
+
+ public final void testBuildDetailsHttpServletRequestUnmappedUserRoles() {
+ String[] mappedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
+ String[] roles = new String[] { "Role1", "Role2", "Role3", "Role4", "Role5" };
+ String[] expectedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
+ testDetails(mappedRoles, roles, expectedRoles);
+ }
+
+ public final void testBuildDetailsHttpServletRequestPartialUserRoles() {
+ String[] mappedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
+ String[] roles = new String[] { "Role2", "Role3" };
+ String[] expectedRoles = new String[] { "Role2", "Role3" };
+ testDetails(mappedRoles, roles, expectedRoles);
+ }
+
+ public final void testBuildDetailsHttpServletRequestPartialAndUnmappedUserRoles() {
+ String[] mappedRoles = new String[] { "Role1", "Role2", "Role3", "Role4" };
+ String[] roles = new String[] { "Role2", "Role3", "Role5" };
+ String[] expectedRoles = new String[] { "Role2", "Role3" };
+ testDetails(mappedRoles, roles, expectedRoles);
+ }
+
+ private void testDetails(String[] mappedRoles, String[] userRoles, String[] expectedRoles) {
+ J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource src = getJ2eeBasedPreAuthenticatedWebAuthenticationDetailsSource(mappedRoles);
+ Object o = src.buildDetails(getRequest("testUser", userRoles));
+ assertNotNull(o);
+ assertTrue("Returned object not of type PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails, actual type: " + o.getClass(),
+ o instanceof PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails);
+ PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails details = (PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails) o;
+ List gas = details.getGrantedAuthorities();
+ assertNotNull("Granted authorities should not be null", gas);
+ assertEquals(expectedRoles.length, gas.size());
+
+ Collection expectedRolesColl = Arrays.asList(expectedRoles);
+ Collection gasRolesSet = new HashSet();
+ for (int i = 0; i < gas.size(); i++) {
+ gasRolesSet.add(gas.get(i).getAuthority());
+ }
+ assertTrue("Granted Authorities do not match expected roles", expectedRolesColl.containsAll(gasRolesSet)
+ && gasRolesSet.containsAll(expectedRolesColl));
+ }
+
+ private final J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource getJ2eeBasedPreAuthenticatedWebAuthenticationDetailsSource(
+ String[] mappedRoles) {
+ J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource result = new J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource();
+ result.setMappableRolesRetriever(getMappableRolesRetriever(mappedRoles));
+ result.setUserRoles2GrantedAuthoritiesMapper(getJ2eeUserRoles2GrantedAuthoritiesMapper());
+ result.setClazz(PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails.class);
+
+ try {
+ result.afterPropertiesSet();
+ } catch (Exception expected) {
+ fail("AfterPropertiesSet throws unexpected exception");
+ }
+ return result;
+ }
+
+ private MappableAttributesRetriever getMappableRolesRetriever(String[] mappedRoles) {
+ SimpleMappableAttributesRetriever result = new SimpleMappableAttributesRetriever();
+ result.setMappableAttributes(new HashSet(Arrays.asList(mappedRoles)));
+ return result;
+ }
+
+ private Attributes2GrantedAuthoritiesMapper getJ2eeUserRoles2GrantedAuthoritiesMapper() {
+ SimpleAttributes2GrantedAuthoritiesMapper result = new SimpleAttributes2GrantedAuthoritiesMapper();
+ result.setAddPrefixIfAlreadyExisting(false);
+ result.setConvertAttributeToLowerCase(false);
+ result.setConvertAttributeToUpperCase(false);
+ result.setAttributePrefix("");
+ return result;
+ }
+
+ private final HttpServletRequest getRequest(final String userName,final String[] aRoles)
+ {
+ MockHttpServletRequest req = new MockHttpServletRequest() {
+ private Set roles = new HashSet(Arrays.asList(aRoles));
+ public boolean isUserInRole(String arg0) {
+ return roles.contains(arg0);
+ }
+ };
+ req.setRemoteUser(userName);
+ return req;
+ }
+}