|
@@ -1,437 +1,468 @@
|
|
|
-/*
|
|
|
- * 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.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.springframework.security.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.springframework.security.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 SPRING_SECURITY_CONTEXT_KEY = HttpSessionContextIntegrationFilter.SPRING_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.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 <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;
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
+/*
|
|
|
+ * 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;
|
|
|
+
|
|
|
+/**
|
|
|
+ * <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.springframework.security.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.springframework.security.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 SecurityContextPersistenceFilter} 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 SecurityContextPersistenceFilter} 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 SPRING_SECURITY_CONTEXT_KEY = HttpSessionSecurityContextRepository.SPRING_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.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 <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;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|