. Improvements to portlet session handling in Login/Logout situations

- Storing of "inPortal" flag in a Threadlocal
 - No longer invalidate portlet session on logout - clear session by hand instead
   - Makes it easier to integrate with other JSR-168 vendors such as Liferay
. Added the current template NodeRef to the default templating model
   - Accessable as an object in the root of the templating model called "template"
. Added the current script NodeRef to the default scripting model
   - Accessable as a root scope object called "script"

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2934 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2006-05-22 13:25:58 +00:00
parent d3a6eb447f
commit 7ef5ae9ad7
6 changed files with 34 additions and 21 deletions

View File

@@ -62,7 +62,7 @@ public class Application
public static final String MESSAGE_BUNDLE = "alfresco.messages.webclient"; public static final String MESSAGE_BUNDLE = "alfresco.messages.webclient";
private static boolean inPortalServer = false; private static ThreadLocal<Boolean> inPortalServer = new ThreadLocal<Boolean>();
private static StoreRef repoStoreRef; private static StoreRef repoStoreRef;
private static String rootPath; private static String rootPath;
private static String companyRootId; private static String companyRootId;
@@ -87,7 +87,7 @@ public class Application
*/ */
public static void setInPortalServer(boolean inPortal) public static void setInPortalServer(boolean inPortal)
{ {
inPortalServer = inPortal; inPortalServer.set(inPortal);
} }
/** /**
@@ -97,7 +97,7 @@ public class Application
*/ */
public static boolean inPortalServer() public static boolean inPortalServer()
{ {
return inPortalServer; return (inPortalServer.get() != null ? inPortalServer.get() : false);
} }
/** /**

View File

@@ -174,16 +174,17 @@ public class ContextListener implements ServletContextListener, HttpSessionListe
{ {
if (logger.isDebugEnabled()) logger.debug("HTTP session destroyed: " + event.getSession().getId()); if (logger.isDebugEnabled()) logger.debug("HTTP session destroyed: " + event.getSession().getId());
User user; String userKey;
if (Application.inPortalServer() == false) if (Application.inPortalServer() == false)
{ {
user = (User)event.getSession().getAttribute(AuthenticationHelper.AUTHENTICATION_USER); userKey = AuthenticationHelper.AUTHENTICATION_USER;
} }
else else
{ {
user = (User)event.getSession().getAttribute(AlfrescoFacesPortlet.MANAGED_BEAN_PREFIX + AuthenticationHelper.AUTHENTICATION_USER); userKey = AlfrescoFacesPortlet.MANAGED_BEAN_PREFIX + AuthenticationHelper.AUTHENTICATION_USER;
} }
User user = (User)event.getSession().getAttribute(userKey);
if (user != null) if (user != null)
{ {
// invalidate ticket and clear the Security context for this thread // invalidate ticket and clear the Security context for this thread
@@ -191,7 +192,7 @@ public class ContextListener implements ServletContextListener, HttpSessionListe
AuthenticationService authService = (AuthenticationService)ctx.getBean("authenticationService"); AuthenticationService authService = (AuthenticationService)ctx.getBean("authenticationService");
authService.invalidateTicket(user.getTicket()); authService.invalidateTicket(user.getTicket());
authService.clearCurrentSecurityContext(); authService.clearCurrentSecurityContext();
event.getSession().removeAttribute(AuthenticationHelper.AUTHENTICATION_USER); event.getSession().removeAttribute(userKey);
} }
} }
} }

View File

@@ -107,6 +107,8 @@ public final class AuthenticationHelper
} }
else else
{ {
// TODO: this prefix is not consistent between JSR-168 vendors!
// we need a solution for each vendor?
user = (User)session.getAttribute(AlfrescoFacesPortlet.MANAGED_BEAN_PREFIX + AUTHENTICATION_USER); user = (User)session.getAttribute(AlfrescoFacesPortlet.MANAGED_BEAN_PREFIX + AUTHENTICATION_USER);
} }

View File

@@ -168,7 +168,7 @@ public class TemplateContentServlet extends BaseServlet
} }
// create the model - put the supplied noderef in as space/document as appropriate // create the model - put the supplied noderef in as space/document as appropriate
Object model = getModel(serviceRegistry, req, nodeRef); Object model = getModel(serviceRegistry, req, templateRef, nodeRef);
// process the template against the node content directly to the response output stream // process the template against the node content directly to the response output stream
// assuming the repo is capable of streaming in chunks, this should allow large files // assuming the repo is capable of streaming in chunks, this should allow large files
@@ -218,11 +218,12 @@ public class TemplateContentServlet extends BaseServlet
* *
* @param services ServiceRegistry required for TemplateNode construction * @param services ServiceRegistry required for TemplateNode construction
* @param req Http request - for accessing Session and url args * @param req Http request - for accessing Session and url args
* @param templateRef NodeRef of the template itself
* @param nodeRef NodeRef of the space/document to process template against * @param nodeRef NodeRef of the space/document to process template against
* *
* @return an object model ready for executing template against * @return an object model ready for executing template against
*/ */
private Object getModel(ServiceRegistry services, HttpServletRequest req, NodeRef nodeRef) private Object getModel(ServiceRegistry services, HttpServletRequest req, NodeRef templateRef, NodeRef nodeRef)
{ {
// build FreeMarker default model and merge // build FreeMarker default model and merge
Map root = DefaultModelHelper.buildDefaultModel(services, Application.getCurrentUser(req.getSession())); Map root = DefaultModelHelper.buildDefaultModel(services, Application.getCurrentUser(req.getSession()));
@@ -231,6 +232,7 @@ public class TemplateContentServlet extends BaseServlet
TemplateNode node = new TemplateNode(nodeRef, services, this.imageResolver); TemplateNode node = new TemplateNode(nodeRef, services, this.imageResolver);
root.put("space", node); root.put("space", node);
root.put("document", node); root.put("document", node);
root.put("template", new TemplateNode(templateRef, services, this.imageResolver));
// add URL arguments as a map called 'args' to the root of the model // add URL arguments as a map called 'args' to the root of the model
Map<String, String> args = new HashMap<String, String>(8, 1.0f); Map<String, String> args = new HashMap<String, String>(8, 1.0f);

View File

@@ -87,6 +87,7 @@ public final class ExecuteScriptCommand implements Command
personRef, personRef,
new NodeRef(Repository.getStoreRef(), Application.getCompanyRootId()), new NodeRef(Repository.getStoreRef(), Application.getCompanyRootId()),
(NodeRef)nodeService.getProperty(personRef, ContentModel.PROP_HOMEFOLDER), (NodeRef)nodeService.getProperty(personRef, ContentModel.PROP_HOMEFOLDER),
scriptRef,
docRef, docRef,
spaceRef, spaceRef,
DefaultModelHelper.imageResolver); DefaultModelHelper.imageResolver);

View File

@@ -27,11 +27,9 @@ import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext; import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem; import javax.faces.model.SelectItem;
import javax.faces.validator.ValidatorException; import javax.faces.validator.ValidatorException;
import javax.portlet.PortletRequest;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.alfresco.config.Config; import org.alfresco.config.Config;
import org.alfresco.config.ConfigService;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationException; import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.InvalidNodeRefException;
@@ -305,14 +303,14 @@ public class LoginBean
// if a redirect URL has been provided then use that // if a redirect URL has been provided then use that
// this allows servlets etc. to provide a URL to return too after a successful login // this allows servlets etc. to provide a URL to return too after a successful login
String redirectURL = (String)fc.getExternalContext().getSessionMap().get(LOGIN_REDIRECT_KEY); String redirectURL = (String)session.get(LOGIN_REDIRECT_KEY);
if (redirectURL != null) if (redirectURL != null)
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("Redirect URL found: " + redirectURL); logger.debug("Redirect URL found: " + redirectURL);
// remove redirect URL from session // remove redirect URL from session
fc.getExternalContext().getSessionMap().remove(LOGIN_REDIRECT_KEY); session.remove(LOGIN_REDIRECT_KEY);
try try
{ {
@@ -355,30 +353,39 @@ public class LoginBean
{ {
FacesContext context = FacesContext.getCurrentInstance(); FacesContext context = FacesContext.getCurrentInstance();
Map session = context.getExternalContext().getSessionMap();
User user = (User) session.get(AuthenticationHelper.AUTHENTICATION_USER);
// need to capture this value before invalidating the session // need to capture this value before invalidating the session
boolean externalAuth = isAlfrescoAuth(); boolean externalAuth = isAlfrescoAuth();
// Invalidate Session for this user. // Invalidate Session for this user.
// This causes the sessionDestroyed() event to be processed by ContextListener
// which is responsible for invalidating the ticket and clearing the security context
if (Application.inPortalServer() == false) if (Application.inPortalServer() == false)
{ {
// This causes the sessionDestroyed() event to be processed by ContextListener
// which is responsible for invalidating the ticket and clearing the security context
HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest(); HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
request.getSession().invalidate(); request.getSession().invalidate();
} }
else else
{ {
PortletRequest request = (PortletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest(); Map session = context.getExternalContext().getSessionMap();
request.getPortletSession().invalidate(); User user = (User)session.get(AuthenticationHelper.AUTHENTICATION_USER);
if (user != null)
{
// invalidate ticket and clear the Security context for this thread
authenticationService.invalidateTicket(user.getTicket());
authenticationService.clearCurrentSecurityContext();
}
// remove all objects from our session by hand
// we do this as invalidating the Portal session would invalidate all other portlets!
for (Object key : session.keySet())
{
session.remove(key);
}
} }
// Request that the username cookie state is removed - this is not // Request that the username cookie state is removed - this is not
// possible from JSF - so instead we setup a session variable // possible from JSF - so instead we setup a session variable
// which will be detected by the login.jsp/Portlet as appropriate. // which will be detected by the login.jsp/Portlet as appropriate.
session = context.getExternalContext().getSessionMap(); Map session = context.getExternalContext().getSessionMap();
session.put(AuthenticationHelper.SESSION_INVALIDATED, true); session.put(AuthenticationHelper.SESSION_INVALIDATED, true);
// set language to last used // set language to last used