. Final phase of web-client Guest Access

. Fix of UserTransaction handling in AuthenticationHelper - very noticable when Guest access fails on older (pre 1.2) databases
. Refactoring of all servlet authentication patterns to be consistent and use a helper so all support Guest and Ticket arguments
. Fix to external URL generation on Document and Space Details pages

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2214 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2006-01-26 12:38:19 +00:00
parent 43640326e5
commit b36a235769
10 changed files with 474 additions and 388 deletions

View File

@@ -48,26 +48,48 @@ import org.springframework.web.context.support.WebApplicationContextUtils;
/** /**
* Helper to authenticate the current user using available Ticket information. * Helper to authenticate the current user using available Ticket information.
* <p>
* User information is looked up in the Session. If found the ticket is retrieved and validated.
* If the ticket is invalid then a redirect is performed to the login page.
* <p>
* If no User info is found then a search will be made for a previous username stored in a Cookie
* value. If the username if found then a redirect to the Login page will occur. If no username
* is found then Guest access login will be attempted by the system. Guest access can be forced
* with the appropriate method call.
* *
* @author Kevin Roast * @author Kevin Roast
*/ */
public final class AuthenticationHelper public final class AuthenticationHelper
{ {
public static final String FACES_SERVLET = "/faces";
/** session variables */
public static final String AUTHENTICATION_USER = "_alfAuthTicket"; public static final String AUTHENTICATION_USER = "_alfAuthTicket";
public static final String SESSION_USERNAME = "_alfLastUser"; public static final String SESSION_USERNAME = "_alfLastUser";
public static final String SESSION_INVALIDATED = "_alfSessionInvalid"; public static final String SESSION_INVALIDATED = "_alfSessionInvalid";
/** JSF bean IDs */
public static final String LOGIN_BEAN = "LoginBean"; public static final String LOGIN_BEAN = "LoginBean";
/** public service bean IDs **/
private static final String AUTHENTICATION_SERVICE = "AuthenticationService";
private static final String UNPROTECTED_AUTH_SERVICE = "authenticationService";
private static final String PERSON_SERVICE = "personService";
/** cookie names */
private static final String COOKIE_ALFUSER = "alfUser"; private static final String COOKIE_ALFUSER = "alfUser";
private static Log logger = LogFactory.getLog(AuthenticationHelper.class); private static Log logger = LogFactory.getLog(AuthenticationHelper.class);
/** /**
* Helper to authenticate the current user using session based Ticket information. * Helper to authenticate the current user using session based Ticket information.
* <p> * <p>
* User information is looked up in the Session. If found the ticket is retrieved and validated. * User information is looked up in the Session. If found the ticket is retrieved and validated.
* If no User info is found or the ticket is invalid then a redirect is performed to the login page. * If no User info is found or the ticket is invalid then a redirect is performed to the login page.
* *
* @param guest True to force a Guest login attempt
*
* @return AuthenticationStatus result. * @return AuthenticationStatus result.
*/ */
public static AuthenticationStatus authenticate( public static AuthenticationStatus authenticate(
@@ -91,10 +113,14 @@ public final class AuthenticationHelper
// setup the authentication context // setup the authentication context
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(context); WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
AuthenticationService auth = (AuthenticationService)wc.getBean(ServletHelper.AUTHENTICATION_SERVICE); AuthenticationService auth = (AuthenticationService)wc.getBean(AUTHENTICATION_SERVICE);
if (user == null || guest) if (user == null || guest)
{ {
// Check for the session invalidated flag - this is set by the Logout action in the LoginBean
// it signals a forced Logout and means we should not immediately attempt a relogin as Guest.
// The attribute is removed from the session by the login.jsp page after the Cookie containing
// the last stored username string is cleared.
if (session.getAttribute(AuthenticationHelper.SESSION_INVALIDATED) == null) if (session.getAttribute(AuthenticationHelper.SESSION_INVALIDATED) == null)
{ {
Cookie authCookie = getAuthCookie(httpRequest); Cookie authCookie = getAuthCookie(httpRequest);
@@ -112,7 +138,7 @@ public final class AuthenticationHelper
tx.begin(); tx.begin();
NodeService nodeService = services.getNodeService(); NodeService nodeService = services.getNodeService();
PersonService personService = (PersonService)wc.getBean(ServletHelper.PERSON_SERVICE); PersonService personService = (PersonService)wc.getBean(PERSON_SERVICE);
NodeRef guestRef = personService.getPerson(PermissionService.GUEST); NodeRef guestRef = personService.getPerson(PermissionService.GUEST);
user = new User(PermissionService.GUEST, auth.getCurrentTicket(), guestRef); user = new User(PermissionService.GUEST, auth.getCurrentTicket(), guestRef);
NodeRef guestHomeRef = (NodeRef)nodeService.getProperty(guestRef, ContentModel.PROP_HOMEFOLDER); NodeRef guestHomeRef = (NodeRef)nodeService.getProperty(guestRef, ContentModel.PROP_HOMEFOLDER);
@@ -125,6 +151,7 @@ public final class AuthenticationHelper
user.setHomeSpaceId(guestHomeRef.getId()); user.setHomeSpaceId(guestHomeRef.getId());
tx.commit(); tx.commit();
tx = null; // clear this so we know not to rollback
// store the User object in the Session - the authentication servlet will then proceed // store the User object in the Session - the authentication servlet will then proceed
session.setAttribute(AuthenticationHelper.AUTHENTICATION_USER, user); session.setAttribute(AuthenticationHelper.AUTHENTICATION_USER, user);
@@ -132,6 +159,9 @@ public final class AuthenticationHelper
// Set the current locale // Set the current locale
I18NUtil.setLocale(Application.getLanguage(httpRequest.getSession())); I18NUtil.setLocale(Application.getLanguage(httpRequest.getSession()));
// remove the session invalidated flag
session.removeAttribute(AuthenticationHelper.SESSION_INVALIDATED);
// it is the responsibilty of the caller to handle the Guest return status // it is the responsibilty of the caller to handle the Guest return status
return AuthenticationStatus.Guest; return AuthenticationStatus.Guest;
} }
@@ -142,19 +172,26 @@ public final class AuthenticationHelper
catch (AccessDeniedException accessError) catch (AccessDeniedException accessError)
{ {
// Guest is unable to access either properties on Person // Guest is unable to access either properties on Person
//AuthenticationService smallAuth = (AuthenticationService)wc.getBean(UNPROTECTED_AUTH_SERVICE);
//smallAuth.invalidateTicket(smallAuth.getCurrentTicket());
logger.warn("Unable to login as Guest: " + accessError.getMessage()); logger.warn("Unable to login as Guest: " + accessError.getMessage());
} }
catch (Throwable e) catch (Throwable e)
{ {
// Guest access not allowed - some other kind of serious failure to report // Some other kind of serious failure to report
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} //AuthenticationService smallAuth = (AuthenticationService)wc.getBean(UNPROTECTED_AUTH_SERVICE);
//smallAuth.invalidateTicket(smallAuth.getCurrentTicket());
throw new AlfrescoRuntimeException("Failed to authenticate as Guest user.", e); throw new AlfrescoRuntimeException("Failed to authenticate as Guest user.", e);
} }
finally
{
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
}
} }
} }
// no user/ticket found or session invalidated by user (logout) - redirect to login page // no user/ticket found or session invalidated by user (logout) - redirect to login page
httpResponse.sendRedirect(httpRequest.getContextPath() + "/faces" + Application.getLoginPage(context)); httpResponse.sendRedirect(httpRequest.getContextPath() + FACES_SERVLET + Application.getLoginPage(context));
return AuthenticationStatus.Failure; return AuthenticationStatus.Failure;
} }
@@ -167,7 +204,7 @@ public final class AuthenticationHelper
catch (AuthenticationException authErr) catch (AuthenticationException authErr)
{ {
// expired ticket - redirect to login page // expired ticket - redirect to login page
httpResponse.sendRedirect(httpRequest.getContextPath() + "/faces" + Application.getLoginPage(context)); httpResponse.sendRedirect(httpRequest.getContextPath() + FACES_SERVLET + Application.getLoginPage(context));
return AuthenticationStatus.Failure; return AuthenticationStatus.Failure;
} }
@@ -195,7 +232,7 @@ public final class AuthenticationHelper
{ {
// setup the authentication context // setup the authentication context
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(context); WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
AuthenticationService auth = (AuthenticationService)wc.getBean(ServletHelper.AUTHENTICATION_SERVICE); AuthenticationService auth = (AuthenticationService)wc.getBean(AUTHENTICATION_SERVICE);
try try
{ {
auth.validate(ticket); auth.validate(ticket);

View File

@@ -41,7 +41,6 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application; import org.alfresco.web.app.Application;
import org.alfresco.web.bean.LoginBean;
import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.Utils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -66,7 +65,10 @@ import org.apache.commons.logging.LogFactory;
* To retrieve the content of a specific model property, use a 'property' arg, providing the workspace, * To retrieve the content of a specific model property, use a 'property' arg, providing the workspace,
* node ID AND the qualified name of the property. * node ID AND the qualified name of the property.
* <p> * <p>
* The URL may be followed by a valid ticket argument for authentication: ?ticket=1234567890 * Like most Alfresco servlets, the URL may be followed by a valid 'ticket' argument for authentication:
* ?ticket=1234567890
* <p>
* And/or also followed by the "?guest=true" argument to force guest access login for the URL.
* *
* @author Kevin Roast * @author Kevin Roast
*/ */
@@ -92,93 +94,72 @@ public class DownloadContentServlet extends HttpServlet
protected void doGet(HttpServletRequest req, HttpServletResponse res) protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException throws ServletException, IOException
{ {
ServletOutputStream out = res.getOutputStream(); // The URL contains multiple parts
// /alfresco/download/attach/workspace/SpacesStore/0000-0000-0000-0000/myfile.pdf
// the protocol, followed by the store, followed by the Id
// the last part is only used for mimetype and browser use
// may be followed by valid ticket for pre-authenticated usage: ?ticket=1234567890
String uri = req.getRequestURI();
if (logger.isDebugEnabled())
logger.debug("Processing URL: " + uri + (req.getQueryString() != null ? ("?" + req.getQueryString()) : ""));
AuthenticationStatus status = ServletHelper.servletAuthenticate(req, res, getServletContext());
if (status == AuthenticationStatus.Failure)
{
return;
}
// TODO: add compression here?
// see http://servlets.com/jservlet2/examples/ch06/ViewResourceCompress.java for example
// only really needed if we don't use the built in compression of the servlet container
StringTokenizer t = new StringTokenizer(uri, "/");
if (t.countTokens() < 7)
{
throw new IllegalArgumentException("Download URL did not contain all required args: " + uri);
}
t.nextToken(); // skip web app name
t.nextToken(); // skip servlet name
String attachToken = t.nextToken();
boolean attachment = attachToken.equals(ARG_ATTACH);
StoreRef storeRef = new StoreRef(t.nextToken(), t.nextToken());
String id = t.nextToken();
String filename = t.nextToken();
// get property qualified name
QName propertyQName = null;
String property = req.getParameter(ARG_PROPERTY);
if (property == null || property.length() == 0)
{
propertyQName = ContentModel.PROP_CONTENT;
}
else
{
propertyQName = QName.createQName(property);
}
NodeRef nodeRef = new NodeRef(storeRef, id);
if (logger.isDebugEnabled())
{
logger.debug("Found NodeRef: " + nodeRef.toString());
logger.debug("Will use filename: " + filename);
logger.debug("For property: " + propertyQName);
logger.debug("With attachment mode: " + attachment);
}
if (attachment == true)
{
// set header based on filename - will force a Save As from the browse if it doesn't recognise it
// this is better than the default response of the browse trying to display the contents!
// TODO: make this configurable - and check it does not prevent streaming of large files
res.setHeader("Content-Disposition", "attachment;filename=\"" + URLDecoder.decode(filename, "UTF-8") + '"');
}
try try
{ {
// The URL contains multiple parts
// /alfresco/download/attach/workspace/SpacesStore/0000-0000-0000-0000/myfile.pdf
// the protocol, followed by the store, followed by the Id
// the last part is only used for mimetype and browser use
// may be followed by valid ticket for pre-authenticated usage: ?ticket=1234567890
String uri = req.getRequestURI();
if (logger.isDebugEnabled())
logger.debug("Processing URL: " + uri + (req.getQueryString() != null ? ("?" + req.getQueryString()) : ""));
// see if a ticket or guest parameter has been supplied
AuthenticationStatus status;
String ticket = req.getParameter(ServletHelper.ARG_TICKET);
if (ticket != null && ticket.length() != 0)
{
status = AuthenticationHelper.authenticate(getServletContext(), req, res, ticket);
}
else
{
boolean forceGuest = false;
String guest = req.getParameter(ServletHelper.ARG_GUEST);
if (guest != null)
{
forceGuest = Boolean.parseBoolean(guest);
}
status = AuthenticationHelper.authenticate(getServletContext(), req, res, forceGuest);
}
if (status == AuthenticationStatus.Failure)
{
// authentication failed - no point returning the content as we haven't logged in yet
// so end servlet execution and save the URL so the login page knows what to do later
req.getSession().setAttribute(LoginBean.LOGIN_REDIRECT_KEY, uri);
return;
}
// TODO: add compression here?
// see http://servlets.com/jservlet2/examples/ch06/ViewResourceCompress.java for example
// only really needed if we don't use the built in compression of the servlet container
StringTokenizer t = new StringTokenizer(uri, "/");
if (t.countTokens() < 7)
{
throw new IllegalArgumentException("Download URL did not contain all required args: " + uri);
}
t.nextToken(); // skip web app name
t.nextToken(); // skip servlet name
String attachToken = t.nextToken();
boolean attachment = attachToken.equals(ARG_ATTACH);
StoreRef storeRef = new StoreRef(t.nextToken(), t.nextToken());
String id = t.nextToken();
String filename = t.nextToken();
// get property qualified name
QName propertyQName = null;
String property = req.getParameter(ARG_PROPERTY);
if (property == null || property.length() == 0)
{
propertyQName = ContentModel.PROP_CONTENT;
}
else
{
propertyQName = QName.createQName(property);
}
NodeRef nodeRef = new NodeRef(storeRef, id);
if (logger.isDebugEnabled())
{
logger.debug("Found NodeRef: " + nodeRef.toString());
logger.debug("Will use filename: " + filename);
logger.debug("For property: " + propertyQName);
logger.debug("With attachment mode: " + attachment);
}
if (attachment == true)
{
// set header based on filename - will force a Save As from the browse if it doesn't recognise it
// this is better than the default response of the browse trying to display the contents!
// TODO: make this configurable - and check it does not prevent streaming of large files
res.setHeader("Content-Disposition", "attachment;filename=\"" + URLDecoder.decode(filename, "UTF-8") + '"');
}
// get the services we need to retrieve the content // get the services we need to retrieve the content
ServiceRegistry serviceRegistry = ServletHelper.getServiceRegistry(getServletContext()); ServiceRegistry serviceRegistry = ServletHelper.getServiceRegistry(getServletContext());
ContentService contentService = serviceRegistry.getContentService(); ContentService contentService = serviceRegistry.getContentService();
@@ -234,10 +215,6 @@ public class DownloadContentServlet extends HttpServlet
{ {
throw new AlfrescoRuntimeException("Error during download content servlet processing: " + err.getMessage(), err); throw new AlfrescoRuntimeException("Error during download content servlet processing: " + err.getMessage(), err);
} }
finally
{
out.close();
}
} }
/** /**

View File

@@ -20,12 +20,18 @@ import java.io.IOException;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.alfresco.web.bean.LoginBean; import org.alfresco.repo.webdav.WebDAVServlet;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.web.bean.BrowseBean;
import org.alfresco.web.bean.NavigationBean;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -39,7 +45,11 @@ import org.apache.commons.logging.LogFactory;
* <p> * <p>
* <code>http://&lt;server&gt;/alfresco/navigate/&lt;outcome&gt;[/&lt;workspace&gt;/&lt;store&gt;/&lt;nodeId&gt;]</code> or <br/> * <code>http://&lt;server&gt;/alfresco/navigate/&lt;outcome&gt;[/&lt;workspace&gt;/&lt;store&gt;/&lt;nodeId&gt;]</code> or <br/>
* <code>http://&lt;server&gt;/alfresco/navigate/&lt;outcome&gt;[/webdav/&lt;path/to/node&gt;]</code> * <code>http://&lt;server&gt;/alfresco/navigate/&lt;outcome&gt;[/webdav/&lt;path/to/node&gt;]</code>
* </p> * <p>
* Like most Alfresco servlets, the URL may be followed by a valid 'ticket' argument for authentication:
* ?ticket=1234567890
* <p>
* And/or also followed by the "?guest=true" argument to force guest access login for the URL.
* *
* @author Kevin Roast * @author Kevin Roast
*/ */
@@ -49,6 +59,11 @@ public class ExternalAccessServlet extends HttpServlet
private static Log logger = LogFactory.getLog(ExternalAccessServlet.class); private static Log logger = LogFactory.getLog(ExternalAccessServlet.class);
private final static String OUTCOME_DOCDETAILS = "showDocDetails";
private final static String OUTCOME_SPACEDETAILS = "showSpaceDetails";
private final static String OUTCOME_BROWSE = "browse";
private static final String ARG_TEMPLATE = "template";
/** /**
* @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
@@ -56,20 +71,16 @@ public class ExternalAccessServlet extends HttpServlet
protected void service(HttpServletRequest req, HttpServletResponse res) protected void service(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException throws ServletException, IOException
{ {
boolean forceGuest = false;
String guest = req.getParameter(ServletHelper.ARG_GUEST);
if (guest != null)
{
forceGuest = Boolean.parseBoolean(guest);
}
AuthenticationStatus status = AuthenticationHelper.authenticate(getServletContext(), req, res, forceGuest);
// The URL contains multiple parts
// /alfresco/navigate/<outcome>
String uri = req.getRequestURI(); String uri = req.getRequestURI();
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("Processing URL: " + uri); logger.debug("Processing URL: " + uri + (req.getQueryString() != null ? ("?" + req.getQueryString()) : ""));
AuthenticationStatus status = ServletHelper.servletAuthenticate(req, res, getServletContext());
if (status == AuthenticationStatus.Failure)
{
return;
}
StringTokenizer t = new StringTokenizer(uri, "/"); StringTokenizer t = new StringTokenizer(uri, "/");
int count = t.countTokens(); int count = t.countTokens();
@@ -82,31 +93,101 @@ public class ExternalAccessServlet extends HttpServlet
String outcome = t.nextToken(); String outcome = t.nextToken();
// get rest of the tokens // get rest of the tokens arguments
String[] tokens = new String[count - 3]; String[] args = new String[count - 3];
for (int i=0; i<count - 3; i++) for (int i=0; i<count - 3; i++)
{ {
tokens[i] = t.nextToken(); args[i] = t.nextToken();
} }
// set the session variable so the login bean knows which outcome to use if (logger.isDebugEnabled())
req.getSession().setAttribute(LoginBean.LOGIN_OUTCOME_KEY, outcome); logger.debug("External outcome found: " + outcome);
// set the args if any // we almost always need this bean reference
req.getSession().setAttribute(LoginBean.LOGIN_OUTCOME_ARGS, tokens); FacesContext fc = ServletHelper.getFacesContext(req, res, getServletContext());
BrowseBean browseBean = (BrowseBean)ServletHelper.getManagedBean(fc, "BrowseBean");
if (status == AuthenticationStatus.Success || status == AuthenticationStatus.Guest) // setup is required for certain outcome requests
if (OUTCOME_DOCDETAILS.equals(outcome))
{ {
// clear the User object from the Session - this will force a relogin NodeRef nodeRef = null;
// we do this so the outcome from the login page can then be changed
req.getSession().removeAttribute(AuthenticationHelper.AUTHENTICATION_USER);
if (logger.isDebugEnabled()) if (args[0].equals(WebDAVServlet.WEBDAV_PREFIX))
logger.debug("Removing User session - will redirect via login page..."); {
nodeRef = ServletHelper.resolveWebDAVPath(fc, args);
}
else if (args.length == 3)
{
StoreRef storeRef = new StoreRef(args[0], args[1]);
nodeRef = new NodeRef(storeRef, args[2]);
}
// redirect to root URL will force the login page to appear via the Authentication Filter if (nodeRef != null)
res.sendRedirect(req.getContextPath()); {
// setup the Document on the browse bean
// TODO: the browse bean should accept a full NodeRef - not just an ID
browseBean.setupContentAction(nodeRef.getId(), true);
}
} }
else if (OUTCOME_SPACEDETAILS.equals(outcome))
{
NodeRef nodeRef = null;
if (args[0].equals(WebDAVServlet.WEBDAV_PREFIX))
{
nodeRef = ServletHelper.resolveWebDAVPath(fc, args);
}
else if (args.length == 3)
{
StoreRef storeRef = new StoreRef(args[0], args[1]);
nodeRef = new NodeRef(storeRef, args[2]);
}
if (nodeRef != null)
{
// setup the Space on the browse bean
// TODO: the browse bean should accept a full NodeRef - not just an ID
browseBean.setupSpaceAction(nodeRef.getId(), true);
}
}
else if (OUTCOME_BROWSE.equals(outcome))
{
if (args != null)
{
NodeRef nodeRef = null;
int offset = 0;
if (args.length >= 3)
{
offset = args.length - 3;
StoreRef storeRef = new StoreRef(args[0+offset], args[1+offset]);
nodeRef = new NodeRef(storeRef, args[2+offset]);
// setup the ref as current Id in the global navigation bean
NavigationBean navigator = (NavigationBean)ServletHelper.getManagedBean(fc, "NavigationBean");
navigator.setCurrentNodeId(nodeRef.getId());
//
// TODO: handle this code
/*
// check for view mode first argument
if (args[0].equals(ARG_TEMPLATE))
{
browseBean.setDashboardView(true);
// the above call will auto-navigate to the correct outcome - so we don't!
//externalOutcome = null;
}
*/
}
}
}
// perform the appropriate JSF navigation outcome
NavigationHandler navigationHandler = fc.getApplication().getNavigationHandler();
navigationHandler.handleNavigation(fc, null, outcome);
// perform the forward to the page processed by the Faces servlet
String viewId = fc.getViewRoot().getViewId();
getServletContext().getRequestDispatcher(AuthenticationHelper.FACES_SERVLET + viewId).forward(req, res);
} }
/** /**

View File

@@ -16,11 +16,38 @@
*/ */
package org.alfresco.web.app.servlet; package org.alfresco.web.app.servlet;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import javax.faces.FactoryFinder;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.el.ValueBinding;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.service.ServiceRegistry; import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.LoginBean;
import org.alfresco.web.bean.repository.Repository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils; import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.jsf.FacesContextUtils;
/** /**
* Useful constant values and common methods for Alfresco servlets. * Useful constant values and common methods for Alfresco servlets.
@@ -30,14 +57,13 @@ import org.springframework.web.context.support.WebApplicationContextUtils;
public final class ServletHelper public final class ServletHelper
{ {
/** an existing Ticket can be passed to most servlet for non-session based authentication */ /** an existing Ticket can be passed to most servlet for non-session based authentication */
public static final String ARG_TICKET = "ticket"; private static final String ARG_TICKET = "ticket";
/** forcing guess access is available on most servlets */ /** forcing guess access is available on most servlets */
public static final String ARG_GUEST = "guest"; private static final String ARG_GUEST = "guest";
private static Log logger = LogFactory.getLog(ServletHelper.class);
/** public service bean IDs **/
public static final String AUTHENTICATION_SERVICE = "authenticationService";
public static final String PERSON_SERVICE = "personService";
/** /**
* Return the ServiceRegistry helper instance * Return the ServiceRegistry helper instance
@@ -58,4 +84,152 @@ public final class ServletHelper
private ServletHelper() private ServletHelper()
{ {
} }
/**
* Perform an authentication for the servlet request URI. Processing any "ticket" or
* "guest" URL arguments.
*
* @return AuthenticationStatus
*
* @throws IOException
*/
public static AuthenticationStatus servletAuthenticate(HttpServletRequest req, HttpServletResponse res, ServletContext sc)
throws IOException
{
AuthenticationStatus status;
// see if a ticket or a force Guest parameter has been supplied
String ticket = req.getParameter(ServletHelper.ARG_TICKET);
if (ticket != null && ticket.length() != 0)
{
status = AuthenticationHelper.authenticate(sc, req, res, ticket);
}
else
{
boolean forceGuest = false;
String guest = req.getParameter(ServletHelper.ARG_GUEST);
if (guest != null)
{
forceGuest = Boolean.parseBoolean(guest);
}
status = AuthenticationHelper.authenticate(sc, req, res, forceGuest);
}
if (status == AuthenticationStatus.Failure)
{
// authentication failed - no point returning the content as we haven't logged in yet
// so end servlet execution and save the URL so the login page knows what to do later
req.getSession().setAttribute(LoginBean.LOGIN_REDIRECT_KEY, req.getRequestURI() + (req.getQueryString() != null ? ("?" + req.getQueryString()) : ""));
}
return status;
}
/**
* Return FacesContext made available to servlets and servlet filters.
* {@link http://www.thoughtsabout.net/blog/archives/000033.html}
*
* @return FacesContext
*/
public static FacesContext getFacesContext(ServletRequest req, ServletResponse res, ServletContext sc)
{
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext != null) return facesContext;
FacesContextFactory contextFactory = (FacesContextFactory)FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
LifecycleFactory lifecycleFactory = (LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
// Can get ServletContext here like this:
// ServletContext servletContext = ((HttpServletRequest)request).getSession().getServletContext();
// Doesn't set this instance as the current instance of FacesContext.getCurrentInstance
facesContext = contextFactory.getFacesContext(sc, req, res, lifecycle);
// Set using our inner class
InnerFacesContext.setFacesContextAsCurrent(facesContext);
// set a new viewRoot, otherwise context.getViewRoot returns null
UIViewRoot view = facesContext.getApplication().getViewHandler().createView(facesContext, "/jsp/root");
facesContext.setViewRoot(view);
return facesContext;
}
/**
* We need an inner class to be able to call FacesContext.setCurrentInstance
* since it's a protected method
*/
private abstract static class InnerFacesContext extends FacesContext
{
protected static void setFacesContextAsCurrent(FacesContext facesContext)
{
FacesContext.setCurrentInstance(facesContext);
}
}
/**
* Return a JSF managed bean reference.
*
* @param fc FacesContext
* @param name Name of the managed bean to return
*
* @return the managed bean or null if not found
*/
public static Object getManagedBean(FacesContext fc, String name)
{
ValueBinding vb = fc.getApplication().createValueBinding("#{" + name + "}");
return vb.getValue(fc);
}
/**
* Resolves the given path elements to a NodeRef in the current repository
*
* @param context Faces context
* @param args The elements of the path to lookup
*/
public static NodeRef resolveWebDAVPath(FacesContext context, String[] args)
{
NodeRef nodeRef = null;
List<String> paths = new ArrayList<String>(args.length-1);
FileInfo file = null;
try
{
// create a list of path elements (decode the URL as we go)
for (int x = 1; x < args.length; x++)
{
paths.add(URLDecoder.decode(args[x], "UTF-8"));
}
if (logger.isDebugEnabled())
logger.debug("Attempting to resolve webdav path to NodeRef: " + paths);
// get the company home node to start the search from
NodeRef companyHome = new NodeRef(Repository.getStoreRef(),
Application.getCompanyRootId());
WebApplicationContext wc = FacesContextUtils.getRequiredWebApplicationContext(context);
//WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
FileFolderService ffs = (FileFolderService)wc.getBean("FileFolderService");
file = ffs.resolveNamePath(companyHome, paths);
nodeRef = file.getNodeRef();
}
catch (UnsupportedEncodingException uee)
{
if (logger.isWarnEnabled())
logger.warn("Failed to resolve webdav path", uee);
nodeRef = null;
}
catch (FileNotFoundException fne)
{
if (logger.isWarnEnabled())
logger.debug("Failed to resolve webdav path", fne);
nodeRef = null;
}
return nodeRef;
}
} }

View File

@@ -39,7 +39,6 @@ import org.alfresco.service.cmr.repository.TemplateException;
import org.alfresco.service.cmr.repository.TemplateNode; import org.alfresco.service.cmr.repository.TemplateNode;
import org.alfresco.service.cmr.repository.TemplateService; import org.alfresco.service.cmr.repository.TemplateService;
import org.alfresco.web.app.Application; import org.alfresco.web.app.Application;
import org.alfresco.web.bean.LoginBean;
import org.alfresco.web.ui.repo.component.template.DefaultModelHelper; import org.alfresco.web.ui.repo.component.template.DefaultModelHelper;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -57,10 +56,13 @@ import org.apache.commons.logging.LogFactory;
* identify the node to execute the default template for. The second set of elements encode * identify the node to execute the default template for. The second set of elements encode
* the store and node Id of the template to used if a default is not set or not requested. * the store and node Id of the template to used if a default is not set or not requested.
* <p> * <p>
* The URL may be followed by a valid 'ticket' argument for authentication: ?ticket=1234567890 * The URL may be followed by a 'mimetype' argument specifying the mimetype to return the result as
* <br>
* And may be followed by a 'mimetype' argument specifying the mimetype to return the result as
* on the stream. Otherwise it is assumed that HTML is the default response mimetype. * on the stream. Otherwise it is assumed that HTML is the default response mimetype.
* <p>
* Like most Alfresco servlets, the URL may be followed by a valid 'ticket' argument for authentication:
* ?ticket=1234567890
* <p>
* And/or also followed by the "?guest=true" argument to force guest access login for the URL.
* *
* @author Kevin Roast * @author Kevin Roast
*/ */
@@ -85,67 +87,48 @@ public class TemplateContentServlet extends HttpServlet
protected void doGet(HttpServletRequest req, HttpServletResponse res) protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException throws ServletException, IOException
{ {
String uri = req.getRequestURI();
if (logger.isDebugEnabled())
logger.debug("Processing URL: " + uri + (req.getQueryString() != null ? ("?" + req.getQueryString()) : ""));
AuthenticationStatus status = ServletHelper.servletAuthenticate(req, res, getServletContext());
if (status == AuthenticationStatus.Failure)
{
return;
}
StringTokenizer t = new StringTokenizer(uri, "/");
int tokenCount = t.countTokens();
if (tokenCount < 5)
{
throw new IllegalArgumentException("Download URL did not contain all required args: " + uri);
}
t.nextToken(); // skip web app name
t.nextToken(); // skip servlet name
// get NodeRef to the content
StoreRef storeRef = new StoreRef(t.nextToken(), t.nextToken());
NodeRef nodeRef = new NodeRef(storeRef, t.nextToken());
// get NodeRef to the template if supplied
NodeRef templateRef = null;
if (tokenCount >= 8)
{
storeRef = new StoreRef(t.nextToken(), t.nextToken());
templateRef = new NodeRef(storeRef, t.nextToken());
}
String mimetype = MIMETYPE_HTML;
if (req.getParameter(ARG_MIMETYPE) != null)
{
mimetype = req.getParameter(ARG_MIMETYPE);
}
res.setContentType(mimetype);
try try
{ {
String uri = req.getRequestURI();
if (logger.isDebugEnabled())
logger.debug("Processing URL: " + uri + (req.getQueryString() != null ? ("?" + req.getQueryString()) : ""));
// see if a ticket has been supplied
AuthenticationStatus status;
String ticket = req.getParameter(ServletHelper.ARG_TICKET);
if (ticket != null && ticket.length() != 0)
{
status = AuthenticationHelper.authenticate(getServletContext(), req, res, ticket);
}
else
{
boolean forceGuest = false;
String guest = req.getParameter(ServletHelper.ARG_GUEST);
if (guest != null)
{
forceGuest = Boolean.parseBoolean(guest);
}
status = AuthenticationHelper.authenticate(getServletContext(), req, res, forceGuest);
}
if (status == AuthenticationStatus.Failure)
{
// authentication failed - no point returning the content as we haven't logged in yet
// so end servlet execution and save the URL so the login page knows what to do later
req.getSession().setAttribute(LoginBean.LOGIN_REDIRECT_KEY, uri);
return;
}
StringTokenizer t = new StringTokenizer(uri, "/");
int tokenCount = t.countTokens();
if (tokenCount < 5)
{
throw new IllegalArgumentException("Download URL did not contain all required args: " + uri);
}
t.nextToken(); // skip web app name
t.nextToken(); // skip servlet name
// get NodeRef to the content
StoreRef storeRef = new StoreRef(t.nextToken(), t.nextToken());
NodeRef nodeRef = new NodeRef(storeRef, t.nextToken());
// get NodeRef to the template if supplied
NodeRef templateRef = null;
if (tokenCount >= 8)
{
storeRef = new StoreRef(t.nextToken(), t.nextToken());
templateRef = new NodeRef(storeRef, t.nextToken());
}
String mimetype = MIMETYPE_HTML;
if (req.getParameter(ARG_MIMETYPE) != null)
{
mimetype = req.getParameter(ARG_MIMETYPE);
}
res.setContentType(mimetype);
// get the services we need to retrieve the content // get the services we need to retrieve the content
ServiceRegistry serviceRegistry = ServletHelper.getServiceRegistry(getServletContext()); ServiceRegistry serviceRegistry = ServletHelper.getServiceRegistry(getServletContext());
NodeService nodeService = serviceRegistry.getNodeService(); NodeService nodeService = serviceRegistry.getNodeService();

View File

@@ -17,10 +17,7 @@
package org.alfresco.web.bean; package org.alfresco.web.bean;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@@ -36,14 +33,9 @@ import javax.servlet.http.HttpServletRequest;
import org.alfresco.config.ConfigService; 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.repo.webdav.WebDAVServlet;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.AuthenticationService; import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.web.app.Application; import org.alfresco.web.app.Application;
@@ -114,14 +106,6 @@ public class LoginBean
{ {
this.configService = configService; this.configService = configService;
} }
/**
* @param fileFolderService The FileFolderService to set.
*/
public void setFileFolderService(FileFolderService fileFolderService)
{
this.fileFolderService = fileFolderService;
}
/** /**
* @param val Username from login dialog * @param val Username from login dialog
@@ -276,7 +260,8 @@ public class LoginBean
FacesContext fc = FacesContext.getCurrentInstance(); FacesContext fc = FacesContext.getCurrentInstance();
if (this.username != null && this.password != null) if (this.username != null && this.username.length() != 0 &&
this.password != null && this.password.length() != 0)
{ {
try try
{ {
@@ -284,14 +269,18 @@ public class LoginBean
// Authenticate via the authentication service, then save the details of user in an object // Authenticate via the authentication service, then save the details of user in an object
// in the session - this is used by the servlet filter etc. on each page to check for login // in the session - this is used by the servlet filter etc. on each page to check for login
//this.authenticationService = (AuthenticationService)FacesContextUtils.getRequiredWebApplicationContext(FacesContext.getCurrentInstance()).getBean("authenticationService");
this.authenticationService.authenticate(this.username, this.password.toCharArray()); this.authenticationService.authenticate(this.username, this.password.toCharArray());
// remove the session invalidated flag (used to remove last username cookie by AuthenticationFilter) // remove the session invalidated flag (used to remove last username cookie by AuthenticationFilter)
session.remove(AuthenticationHelper.SESSION_INVALIDATED); session.remove(AuthenticationHelper.SESSION_INVALIDATED);
// setup User object and Home space ID // setup User object and Home space ID
User user = new User(this.authenticationService.getCurrentUserName(), this.authenticationService.getCurrentTicket(), User user = new User(
this.authenticationService.getCurrentUserName(),
this.authenticationService.getCurrentTicket(),
personService.getPerson(this.username)); personService.getPerson(this.username));
NodeRef homeSpaceRef = (NodeRef) this.nodeService.getProperty(personService.getPerson(this.username), ContentModel.PROP_HOMEFOLDER); NodeRef homeSpaceRef = (NodeRef) this.nodeService.getProperty(personService.getPerson(this.username), ContentModel.PROP_HOMEFOLDER);
// check that the home space node exists - else user cannot login // check that the home space node exists - else user cannot login
@@ -305,118 +294,31 @@ public class LoginBean
// the app to continue without redirecting to the login page // the app to continue without redirecting to the login page
session.put(AuthenticationHelper.AUTHENTICATION_USER, user); session.put(AuthenticationHelper.AUTHENTICATION_USER, user);
// if an external outcome has been provided then use that, else use default // if a redirect URL has been provided then use that
String externalOutcome = (String)fc.getExternalContext().getSessionMap().get(LOGIN_OUTCOME_KEY); // this allows servlets etc. to provide a URL to return too after a successful login
if (externalOutcome != null) String redirectURL = (String)fc.getExternalContext().getSessionMap().get(LOGIN_REDIRECT_KEY);
if (redirectURL != null)
{ {
// TODO: This is a quick solution. It would be better to specify the (identifier?)
// of a handler class that would be responsible for processing specific outcome arguments.
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("External outcome found: " + externalOutcome); logger.debug("Redirect URL found: " + redirectURL);
// setup is required for certain outcome requests // remove redirect URL from session
if (OUTCOME_DOCDETAILS.equals(externalOutcome)) fc.getExternalContext().getSessionMap().remove(LOGIN_REDIRECT_KEY);
{
NodeRef nodeRef = null;
String[] args = (String[]) fc.getExternalContext().getSessionMap().get(LOGIN_OUTCOME_ARGS);
if (args[0].equals(WebDAVServlet.WEBDAV_PREFIX))
{
nodeRef = resolveWebDAVPath(fc, args);
}
else if (args.length == 3)
{
StoreRef storeRef = new StoreRef(args[0], args[1]);
nodeRef = new NodeRef(storeRef, args[2]);
}
if (nodeRef != null)
{
// setup the Document on the browse bean
// TODO: the browse bean should accept a full NodeRef - not just an ID
this.browseBean.setupContentAction(nodeRef.getId(), true);
}
}
else if (OUTCOME_SPACEDETAILS.equals(externalOutcome))
{
NodeRef nodeRef = null;
String[] args = (String[]) fc.getExternalContext().getSessionMap().get(LOGIN_OUTCOME_ARGS);
if (args[0].equals(WebDAVServlet.WEBDAV_PREFIX))
{
nodeRef = resolveWebDAVPath(fc, args);
}
else if (args.length == 3)
{
StoreRef storeRef = new StoreRef(args[0], args[1]);
nodeRef = new NodeRef(storeRef, args[2]);
}
if (nodeRef != null)
{
// setup the Space on the browse bean
// TODO: the browse bean should accept a full NodeRef - not just an ID
this.browseBean.setupSpaceAction(nodeRef.getId(), true);
}
}
else if (OUTCOME_BROWSE.equals(externalOutcome))
{
String[] args = (String[]) fc.getExternalContext().getSessionMap().get(LOGIN_OUTCOME_ARGS);
if (args != null)
{
NodeRef nodeRef = null;
int offset = 0;
if (args.length >= 3)
{
offset = args.length - 3;
StoreRef storeRef = new StoreRef(args[0+offset], args[1+offset]);
nodeRef = new NodeRef(storeRef, args[2+offset]);
// setup the ref as current Id in the global navigation bean
this.navigator.setCurrentNodeId(nodeRef.getId());
// check for view mode first argument
if (args[0].equals(LOGIN_ARG_TEMPLATE))
{
this.browseBean.setDashboardView(true);
// the above call will auto-navigate to the correct outcome - so we don't!
externalOutcome = null;
}
}
}
}
fc.getExternalContext().getSessionMap().remove(LOGIN_OUTCOME_KEY); try
return externalOutcome; {
fc.getExternalContext().redirect(redirectURL);
fc.responseComplete();
return null;
}
catch (IOException ioErr)
{
logger.warn("Unable to redirect to url: " + redirectURL);
}
} }
else else
{ {
// if a redirect URL has been provided then use that return "success";
String redirectURL = (String)fc.getExternalContext().getSessionMap().get(LOGIN_REDIRECT_KEY);
if (redirectURL != null)
{
if (logger.isDebugEnabled())
logger.debug("Redirect URL found: " + redirectURL);
// remove URL from session
fc.getExternalContext().getSessionMap().remove(LOGIN_REDIRECT_KEY);
try
{
fc.getExternalContext().redirect(redirectURL);
fc.responseComplete();
return null;
}
catch (IOException ioErr)
{
logger.warn("Unable to redirect to url: " + redirectURL);
}
}
else
{
return "success";
}
} }
} }
catch (AuthenticationException aerr) catch (AuthenticationException aerr)
@@ -481,59 +383,6 @@ public class LoginBean
return alfrescoAuth ? "logout" : "relogin"; return alfrescoAuth ? "logout" : "relogin";
} }
// ------------------------------------------------------------------------------
// Private helpers
/**
* Resolves the given path elements to a NodeRef in the current repository
*
* @param context Faces context
* @param args The elements of the path to lookup
*/
private NodeRef resolveWebDAVPath(FacesContext context, String[] args)
{
NodeRef nodeRef = null;
List<String> paths = new ArrayList<String>(args.length-1);
FileInfo file = null;
try
{
// create a list of path elements (decode the URL as we go)
for (int x = 1; x < args.length; x++)
{
paths.add(URLDecoder.decode(args[x], "UTF-8"));
}
if (logger.isDebugEnabled())
logger.debug("Attempting to resolve webdav path to NodeRef: " + paths);
// get the company home node to start the search from
NodeRef companyHome = new NodeRef(Repository.getStoreRef(),
Application.getCompanyRootId());
file = this.fileFolderService.resolveNamePath(companyHome, paths);
nodeRef = file.getNodeRef();
}
catch (UnsupportedEncodingException uee)
{
if (logger.isWarnEnabled())
logger.warn("Failed to resolve webdav path", uee);
nodeRef = null;
}
catch (FileNotFoundException fne)
{
if (logger.isWarnEnabled())
logger.debug("Failed to resolve webdav path", fne);
nodeRef = null;
}
return nodeRef;
}
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
@@ -550,16 +399,8 @@ public class LoginBean
private static final String MSG_PASSWORD_LENGTH = "login_err_password_length"; private static final String MSG_PASSWORD_LENGTH = "login_err_password_length";
public static final String LOGIN_REDIRECT_KEY = "_alfRedirect"; public static final String LOGIN_REDIRECT_KEY = "_alfRedirect";
public static final String LOGIN_OUTCOME_KEY = "_alfOutcome";
public static final String LOGIN_OUTCOME_ARGS = "_alfOutcomeArgs";
public static final String LOGIN_EXTERNAL_AUTH= "_alfExternalAuth"; public static final String LOGIN_EXTERNAL_AUTH= "_alfExternalAuth";
public final static String OUTCOME_DOCDETAILS = "showDocDetails";
public final static String OUTCOME_SPACEDETAILS = "showSpaceDetails";
public final static String OUTCOME_BROWSE = "browse";
private static final String LOGIN_ARG_TEMPLATE = "template";
/** user name */ /** user name */
private String username = null; private String username = null;
@@ -586,7 +427,4 @@ public class LoginBean
/** ConfigService bean reference */ /** ConfigService bean reference */
private ConfigService configService; private ConfigService configService;
/** FileFolderService bean reference */
private FileFolderService fileFolderService;
} }

View File

@@ -27,7 +27,7 @@
</managed-property> </managed-property>
<managed-property> <managed-property>
<property-name>authenticationService</property-name> <property-name>authenticationService</property-name>
<value>#{authenticationService}</value> <value>#{AuthenticationService}</value>
</managed-property> </managed-property>
<managed-property> <managed-property>
<property-name>personService</property-name> <property-name>personService</property-name>
@@ -45,10 +45,6 @@
<property-name>configService</property-name> <property-name>configService</property-name>
<value>#{configService}</value> <value>#{configService}</value>
</managed-property> </managed-property>
<managed-property>
<property-name>fileFolderService</property-name>
<value>#{FileFolderService}</value>
</managed-property>
</managed-bean> </managed-bean>
<managed-bean> <managed-bean>

View File

@@ -250,7 +250,7 @@
<a:actionLink value="#{msg.download_content}" href="#{DocumentDetailsBean.downloadUrl}" target="new" id="link4" /> <a:actionLink value="#{msg.download_content}" href="#{DocumentDetailsBean.downloadUrl}" target="new" id="link4" />
</td> </td>
<td> <td>
<a href='<a:outputText value="#{DocumentDetailsBean.bookmarkUrl}" id="out1" />' onclick="return false;"><a:outputText value="#{msg.details_page_bookmark}" id="out2" /></a> <a href='<%=request.getContextPath()%><a:outputText value="#{DocumentDetailsBean.bookmarkUrl}" id="out1" />' onclick="return false;"><a:outputText value="#{msg.details_page_bookmark}" id="out2" /></a>
</td> </td>
<td> <td>
<a href='<a:outputText value="#{DocumentDetailsBean.nodeRefUrl}" id="out3" />' onclick="return false;"><a:outputText value="#{msg.noderef_link}" id="out4" /></a> <a href='<a:outputText value="#{DocumentDetailsBean.nodeRefUrl}" id="out3" />' onclick="return false;"><a:outputText value="#{msg.noderef_link}" id="out4" /></a>

View File

@@ -248,7 +248,7 @@
<a:actionLink value="#{msg.view_in_cifs}" href="#{SpaceDetailsBean.cifsPath}" target="new" id="link2" /> <a:actionLink value="#{msg.view_in_cifs}" href="#{SpaceDetailsBean.cifsPath}" target="new" id="link2" />
</td> </td>
<td> <td>
<a href='<a:outputText value="#{SpaceDetailsBean.bookmarkUrl}" id="out1" />' onclick="return false;"><a:outputText value="#{msg.details_page_bookmark}" id="out2" /></a> <a href='<%=request.getContextPath()%><a:outputText value="#{SpaceDetailsBean.bookmarkUrl}" id="out1" />' onclick="return false;"><a:outputText value="#{msg.details_page_bookmark}" id="out2" /></a>
</td> </td>
<td> <td>
<a href='<a:outputText value="#{SpaceDetailsBean.nodeRefUrl}" id="out3" />' onclick="return false;"><a:outputText value="#{msg.noderef_link}" id="out4" /></a> <a href='<a:outputText value="#{SpaceDetailsBean.nodeRefUrl}" id="out3" />' onclick="return false;"><a:outputText value="#{msg.noderef_link}" id="out4" /></a>

View File

@@ -41,7 +41,7 @@
else else
{ {
// setup value used by JSF bean state ready for login page if we find the cookie // setup value used by JSF bean state ready for login page if we find the cookie
if (authCookie != null) if (authCookie != null && authCookie.getValue() != null)
{ {
session.setAttribute(AuthenticationHelper.SESSION_USERNAME, authCookie.getValue()); session.setAttribute(AuthenticationHelper.SESSION_USERNAME, authCookie.getValue());
} }