diff --git a/source/java/org/alfresco/web/app/servlet/AuthenticationFilter.java b/source/java/org/alfresco/web/app/servlet/AuthenticationFilter.java index 280d681cce..84e57263fe 100644 --- a/source/java/org/alfresco/web/app/servlet/AuthenticationFilter.java +++ b/source/java/org/alfresco/web/app/servlet/AuthenticationFilter.java @@ -64,7 +64,10 @@ public class AuthenticationFilter implements Filter // allow the login page to proceed if (httpReq.getRequestURI().endsWith(getLoginPage()) == false) { - if (AuthenticationHelper.authenticate(this.context, httpReq, (HttpServletResponse)res)) + AuthenticationStatus status = + AuthenticationHelper.authenticate(this.context, httpReq, (HttpServletResponse)res); + + if (status == AuthenticationStatus.Success || status == AuthenticationStatus.Guest) { // continue filter chaining chain.doFilter(req, res); diff --git a/source/java/org/alfresco/web/app/servlet/AuthenticationHelper.java b/source/java/org/alfresco/web/app/servlet/AuthenticationHelper.java index ee40374bdf..e7871158e3 100644 --- a/source/java/org/alfresco/web/app/servlet/AuthenticationHelper.java +++ b/source/java/org/alfresco/web/app/servlet/AuthenticationHelper.java @@ -22,10 +22,20 @@ import javax.servlet.ServletContext; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.transaction.UserTransaction; +import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.i18n.I18NUtil; +import org.alfresco.model.ContentModel; import org.alfresco.repo.security.authentication.AuthenticationException; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.transaction.TransactionService; import org.alfresco.web.app.Application; import org.alfresco.web.app.portlet.AlfrescoFacesPortlet; import org.alfresco.web.bean.LoginBean; @@ -54,45 +64,105 @@ public final class AuthenticationHelper * 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. * - * @return true if authentication successful, false otherwise. + * @return AuthenticationStatus result. */ - public static boolean authenticate(ServletContext context, HttpServletRequest httpRequest, HttpServletResponse httpResponse) - throws IOException + public static AuthenticationStatus authenticate( + ServletContext context, HttpServletRequest httpRequest, HttpServletResponse httpResponse) + throws IOException { + HttpSession session = httpRequest.getSession(); + // examine the appropriate session for our User object User user; LoginBean loginBean = null; if (Application.inPortalServer() == false) { - user = (User)httpRequest.getSession().getAttribute(AUTHENTICATION_USER); - loginBean = (LoginBean)httpRequest.getSession().getAttribute(LOGIN_BEAN); + user = (User)session.getAttribute(AUTHENTICATION_USER); + loginBean = (LoginBean)session.getAttribute(LOGIN_BEAN); } else { - user = (User)httpRequest.getSession().getAttribute(AlfrescoFacesPortlet.MANAGED_BEAN_PREFIX + AUTHENTICATION_USER); + user = (User)session.getAttribute(AlfrescoFacesPortlet.MANAGED_BEAN_PREFIX + AUTHENTICATION_USER); } + // setup the authentication context + WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(context); + AuthenticationService auth = (AuthenticationService)ctx.getBean(AUTHENTICATION_SERVICE); + if (user == null) { - // no user/ticket found - redirect to login page + if (session.getAttribute(AuthenticationHelper.SESSION_INVALIDATED) == null) + { + Cookie authCookie = getAuthCookie(httpRequest); + if (authCookie == null) + { + // TODO: "forced" guest access on URLs! + // no previous authentication - attempt Guest access first + UserTransaction tx = null; + try + { + auth.authenticateAsGuest(); + + // if we get here then Guest access was allowed and successful + tx = ((TransactionService)ctx.getBean("TransactionService")).getUserTransaction(); + tx.begin(); + + PersonService personService = (PersonService)ctx.getBean("personService"); + NodeService nodeService = (NodeService)ctx.getBean("nodeService"); + NodeRef guestRef = personService.getPerson(PermissionService.GUEST); + user = new User(PermissionService.GUEST, auth.getCurrentTicket(), guestRef); + NodeRef guestHomeRef = (NodeRef)nodeService.getProperty(guestRef, ContentModel.PROP_HOMEFOLDER); + + // check that the home space node exists - else Guest cannot proceed + if (nodeService.exists(guestHomeRef) == false) + { + throw new InvalidNodeRefException(guestHomeRef); + } + user.setHomeSpaceId(guestHomeRef.getId()); + + tx.commit(); + + // store the User object in the Session - the authentication servlet will then proceed + session.setAttribute(AuthenticationHelper.AUTHENTICATION_USER, user); + + // Set the current locale + I18NUtil.setLocale(Application.getLanguage(httpRequest.getSession())); + + return AuthenticationStatus.Guest; + + // TODO: What now? Any redirects can be performed directly from the appropriate + // servlet entry points, as we are now authenticated and don't + // need to go through the Login screen to gain authentication. + } + catch (AuthenticationException guestError) + { + // Guest access not allowed - continue to login page as usual + } + catch (Throwable e) + { + // Guest access not allowed - some other kind of serious failure to report + try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} + throw new AlfrescoRuntimeException("Failed to authenticate as Guest user.", e); + } + } + } + + // no user/ticket found or session invalidated by user (logout) - redirect to login page httpResponse.sendRedirect(httpRequest.getContextPath() + "/faces" + Application.getLoginPage(context)); - return false; + return AuthenticationStatus.Failure; } else { - // setup the authentication context - WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(context); - AuthenticationService auth = (AuthenticationService)ctx.getBean(AUTHENTICATION_SERVICE); try { auth.validate(user.getTicket()); } catch (AuthenticationException authErr) { - // no user/ticket - redirect to login page + // expired ticket - redirect to login page httpResponse.sendRedirect(httpRequest.getContextPath() + "/faces" + Application.getLoginPage(context)); - return false; + return AuthenticationStatus.Failure; } // set last authentication username cookie value @@ -104,7 +174,7 @@ public final class AuthenticationHelper // Set the current locale I18NUtil.setLocale(Application.getLanguage(httpRequest.getSession())); - return true; + return AuthenticationStatus.Success; } } @@ -113,8 +183,9 @@ public final class AuthenticationHelper * * @return true if authentication successful, false otherwise. */ - public static boolean authenticate(ServletContext context, HttpServletRequest httpRequest, HttpServletResponse httpResponse, String ticket) - throws IOException + public static AuthenticationStatus authenticate( + ServletContext context, HttpServletRequest httpRequest, HttpServletResponse httpResponse, String ticket) + throws IOException { // setup the authentication context WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(context); @@ -125,13 +196,13 @@ public final class AuthenticationHelper } catch (AuthenticationException authErr) { - return false; + return AuthenticationStatus.Failure; } // Set the current locale I18NUtil.setLocale(Application.getLanguage(httpRequest.getSession())); - return true; + return AuthenticationStatus.Success; } /** diff --git a/source/java/org/alfresco/web/app/servlet/AuthenticationStatus.java b/source/java/org/alfresco/web/app/servlet/AuthenticationStatus.java new file mode 100644 index 0000000000..564fcadaed --- /dev/null +++ b/source/java/org/alfresco/web/app/servlet/AuthenticationStatus.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * 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.alfresco.web.app.servlet; + +/** + * @author Kevin Roast + */ +public enum AuthenticationStatus +{ + Success, Failure, Guest; +} diff --git a/source/java/org/alfresco/web/app/servlet/DownloadContentServlet.java b/source/java/org/alfresco/web/app/servlet/DownloadContentServlet.java index 381ff3edbf..7a62083737 100644 --- a/source/java/org/alfresco/web/app/servlet/DownloadContentServlet.java +++ b/source/java/org/alfresco/web/app/servlet/DownloadContentServlet.java @@ -110,20 +110,22 @@ public class DownloadContentServlet extends HttpServlet logger.debug("Processing URL: " + uri + (req.getQueryString() != null ? ("?" + req.getQueryString()) : "")); // see if a ticket has been supplied + AuthenticationStatus status; String ticket = req.getParameter(ARG_TICKET); if (ticket == null || ticket.length() == 0) { - if (AuthenticationHelper.authenticate(getServletContext(), req, res) == false) - { - // 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; - } + status = AuthenticationHelper.authenticate(getServletContext(), req, res); } else { - AuthenticationHelper.authenticate(getServletContext(), req, res, ticket); + status = AuthenticationHelper.authenticate(getServletContext(), req, res, ticket); + } + 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? diff --git a/source/java/org/alfresco/web/app/servlet/ExternalAccessServlet.java b/source/java/org/alfresco/web/app/servlet/ExternalAccessServlet.java index 866344edc4..0c2568a323 100644 --- a/source/java/org/alfresco/web/app/servlet/ExternalAccessServlet.java +++ b/source/java/org/alfresco/web/app/servlet/ExternalAccessServlet.java @@ -56,7 +56,7 @@ public class ExternalAccessServlet extends HttpServlet protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { - boolean alreadyAuthenticated = AuthenticationHelper.authenticate(getServletContext(), req, res); + AuthenticationStatus status = AuthenticationHelper.authenticate(getServletContext(), req, res); // The URL contains multiple parts // /alfresco/navigate/ @@ -89,7 +89,7 @@ public class ExternalAccessServlet extends HttpServlet // set the args if any req.getSession().setAttribute(LoginBean.LOGIN_OUTCOME_ARGS, tokens); - if (alreadyAuthenticated) + if (status == AuthenticationStatus.Success || status == AuthenticationStatus.Guest) { // clear the User object from the Session - this will force a relogin // we do this so the outcome from the login page can then be changed diff --git a/source/java/org/alfresco/web/app/servlet/TemplateContentServlet.java b/source/java/org/alfresco/web/app/servlet/TemplateContentServlet.java index 79ad7d7e09..0ad2408a1b 100644 --- a/source/java/org/alfresco/web/app/servlet/TemplateContentServlet.java +++ b/source/java/org/alfresco/web/app/servlet/TemplateContentServlet.java @@ -96,20 +96,22 @@ public class TemplateContentServlet extends HttpServlet logger.debug("Processing URL: " + uri + (req.getQueryString() != null ? ("?" + req.getQueryString()) : "")); // see if a ticket has been supplied + AuthenticationStatus status; String ticket = req.getParameter(ARG_TICKET); if (ticket == null || ticket.length() == 0) { - if (AuthenticationHelper.authenticate(getServletContext(), req, res) == false) - { - // 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; - } + status = AuthenticationHelper.authenticate(getServletContext(), req, res); } else { - AuthenticationHelper.authenticate(getServletContext(), req, res, ticket); + status = AuthenticationHelper.authenticate(getServletContext(), req, res, ticket); + } + 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, "/"); diff --git a/source/java/org/alfresco/web/bean/AdvancedSearchBean.java b/source/java/org/alfresco/web/bean/AdvancedSearchBean.java index 0e5c46cc22..20edc4f556 100644 --- a/source/java/org/alfresco/web/bean/AdvancedSearchBean.java +++ b/source/java/org/alfresco/web/bean/AdvancedSearchBean.java @@ -1302,7 +1302,7 @@ public class AdvancedSearchBean { userSearchesRef = results.get(0); } - else if (results.size() == 0) + else if (results.size() == 0 && new Node(globalRef).hasPermission(PermissionService.ADD_CHILDREN)) { // attempt to create folder for this user for first time // create the preferences Node for this user diff --git a/source/java/org/alfresco/web/bean/LoginBean.java b/source/java/org/alfresco/web/bean/LoginBean.java index aa88d67d03..56c488ef71 100644 --- a/source/java/org/alfresco/web/bean/LoginBean.java +++ b/source/java/org/alfresco/web/bean/LoginBean.java @@ -278,12 +278,17 @@ public class LoginBean if (this.username != null && this.password != null) { - // 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 try { + Map session = fc.getExternalContext().getSessionMap(); + + // 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 this.authenticationService.authenticate(this.username, this.password.toCharArray()); + // remove the session invalidated flag (used to remove last username cookie by AuthenticationFilter) + session.remove(AuthenticationHelper.SESSION_INVALIDATED); + // setup User object and Home space ID User user = new User(this.authenticationService.getCurrentUserName(), this.authenticationService.getCurrentTicket(), personService.getPerson(this.username)); @@ -298,7 +303,6 @@ public class LoginBean // put the User object in the Session - the authentication servlet will then allow // the app to continue without redirecting to the login page - Map session = fc.getExternalContext().getSessionMap(); session.put(AuthenticationHelper.AUTHENTICATION_USER, user); // if an external outcome has been provided then use that, else use default diff --git a/source/java/org/alfresco/web/bean/NavigationBean.java b/source/java/org/alfresco/web/bean/NavigationBean.java index 10ff5d426a..f379f37efc 100644 --- a/source/java/org/alfresco/web/bean/NavigationBean.java +++ b/source/java/org/alfresco/web/bean/NavigationBean.java @@ -39,6 +39,7 @@ import org.alfresco.service.cmr.repository.Path; import org.alfresco.service.cmr.repository.TemplateImageResolver; import org.alfresco.service.cmr.repository.TemplateNode; import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.web.app.AlfrescoNavigationHandler; import org.alfresco.web.app.Application; @@ -406,6 +407,14 @@ public class NavigationBean this.location = location; } + /** + * @return true if we are currently the special Guest user + */ + public boolean getIsGuest() + { + return Application.getCurrentUser(FacesContext.getCurrentInstance()).getUserName().equals(PermissionService.GUEST); + } + /** * Sets up the dispatch context so that the navigation handler knows * what object is being acted upon diff --git a/source/web/jsp/dialog/document-details.jsp b/source/web/jsp/dialog/document-details.jsp index 85d83b0714..1fdddb0283 100644 --- a/source/web/jsp/dialog/document-details.jsp +++ b/source/web/jsp/dialog/document-details.jsp @@ -250,10 +250,10 @@ - + - + diff --git a/source/web/jsp/dialog/space-details.jsp b/source/web/jsp/dialog/space-details.jsp index fe7f013dc1..8874ece4c2 100644 --- a/source/web/jsp/dialog/space-details.jsp +++ b/source/web/jsp/dialog/space-details.jsp @@ -248,10 +248,10 @@ - + - + diff --git a/source/web/jsp/login.jsp b/source/web/jsp/login.jsp index cb4ac69bf7..d863aa3882 100644 --- a/source/web/jsp/login.jsp +++ b/source/web/jsp/login.jsp @@ -37,7 +37,6 @@ authCookie.setMaxAge(0); response.addCookie(authCookie); } - session.removeAttribute(AuthenticationHelper.SESSION_INVALIDATED); } else { diff --git a/source/web/jsp/parts/titlebar.jsp b/source/web/jsp/parts/titlebar.jsp index 0a4ba3caef..280922da76 100644 --- a/source/web/jsp/parts/titlebar.jsp +++ b/source/web/jsp/parts/titlebar.jsp @@ -46,7 +46,10 @@   - + + + + diff --git a/source/web/jsp/relogin.jsp b/source/web/jsp/relogin.jsp index 5217a2bd34..24e77b079d 100644 --- a/source/web/jsp/relogin.jsp +++ b/source/web/jsp/relogin.jsp @@ -36,7 +36,6 @@ authCookie.setMaxAge(0); response.addCookie(authCookie); } - session.removeAttribute(AuthenticationHelper.SESSION_INVALIDATED); } %> diff --git a/source/web/jsp/users/change-password.jsp b/source/web/jsp/users/change-password.jsp index 29aebb50b4..f6df700969 100644 --- a/source/web/jsp/users/change-password.jsp +++ b/source/web/jsp/users/change-password.jsp @@ -137,14 +137,14 @@ : -  * +  *   : -  * +  *   diff --git a/source/web/jsp/wizard/new-user/person-properties.jsp b/source/web/jsp/wizard/new-user/person-properties.jsp index c135aa17b1..820e2fb4c7 100644 --- a/source/web/jsp/wizard/new-user/person-properties.jsp +++ b/source/web/jsp/wizard/new-user/person-properties.jsp @@ -151,19 +151,19 @@ : -  * +  * : -  * +  * : -  * +  * diff --git a/source/web/jsp/wizard/new-user/user-properties.jsp b/source/web/jsp/wizard/new-user/user-properties.jsp index 28c903e2db..b20b749346 100644 --- a/source/web/jsp/wizard/new-user/user-properties.jsp +++ b/source/web/jsp/wizard/new-user/user-properties.jsp @@ -170,21 +170,21 @@ : -  * +  *   : -  * +  *   : -  * +  *   @@ -202,7 +202,7 @@ : - +