diff --git a/config/alfresco/web-api-application-context.xml b/config/alfresco/web-api-application-context.xml index 51162f69c4..ce37fbfac9 100644 --- a/config/alfresco/web-api-application-context.xml +++ b/config/alfresco/web-api-application-context.xml @@ -8,12 +8,18 @@ - + + + + + + + diff --git a/source/java/org/alfresco/web/api/APIContextAware.java b/source/java/org/alfresco/web/api/APIContextAware.java new file mode 100644 index 0000000000..354279b049 --- /dev/null +++ b/source/java/org/alfresco/web/api/APIContextAware.java @@ -0,0 +1,9 @@ +package org.alfresco.web.api; + +import javax.servlet.ServletContext; + +public interface APIContextAware +{ + + public void setAPIContext(ServletContext context); +} diff --git a/source/java/org/alfresco/web/api/APIService.java b/source/java/org/alfresco/web/api/APIService.java index 6d7f967963..4d9ea4fbfe 100644 --- a/source/java/org/alfresco/web/api/APIService.java +++ b/source/java/org/alfresco/web/api/APIService.java @@ -18,8 +18,6 @@ package org.alfresco.web.api; import java.io.IOException; -import javax.servlet.ServletContext; - /** * API Service * @@ -28,13 +26,6 @@ import javax.servlet.ServletContext; public interface APIService { - /** - * Initialise the Service - * - * @param context - */ - public void init(ServletContext context); - /** * Gets the name of this service * diff --git a/source/java/org/alfresco/web/api/APIServiceRegistry.java b/source/java/org/alfresco/web/api/APIServiceRegistry.java index 34bbc4344b..581646f161 100644 --- a/source/java/org/alfresco/web/api/APIServiceRegistry.java +++ b/source/java/org/alfresco/web/api/APIServiceRegistry.java @@ -20,8 +20,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import javax.servlet.ServletContext; - import org.aopalliance.intercept.MethodInterceptor; import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.support.RegexpMethodPointcutAdvisor; @@ -47,7 +45,7 @@ public class APIServiceRegistry * * @param context */ - public APIServiceRegistry(ServletContext servletContext, ApplicationContext appContext) + public APIServiceRegistry(ApplicationContext appContext) { // retrieve service authenticator MethodInterceptor authenticator = (MethodInterceptor)appContext.getBean("web.api.Authenticator"); @@ -60,7 +58,6 @@ public class APIServiceRegistry { // retrieve service APIService service = apiService.getValue(); - service.init(servletContext); // retrieve http method APIRequest.HttpMethod method = service.getHttpMethod(); diff --git a/source/java/org/alfresco/web/api/APIServlet.java b/source/java/org/alfresco/web/api/APIServlet.java index 7da8b841d5..67dbd685ec 100644 --- a/source/java/org/alfresco/web/api/APIServlet.java +++ b/source/java/org/alfresco/web/api/APIServlet.java @@ -17,7 +17,9 @@ package org.alfresco.web.api; import java.io.IOException; +import java.util.Map; +import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -52,7 +54,8 @@ public class APIServlet extends BaseServlet // Retrieve all web api services and index by http url & http method ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()); - apiServiceRegistry = new APIServiceRegistry(getServletContext(), context); + initContext(context); + apiServiceRegistry = new APIServiceRegistry(context); } @@ -109,4 +112,19 @@ public class APIServlet extends BaseServlet } } + /** + * Initialise any API beans that require a servlet context + * + * @param appContext application context + */ + private void initContext(ApplicationContext appContext) + { + ServletContext servletContext = getServletContext(); + Map contextAwareMap = appContext.getBeansOfType(APIContextAware.class, false, false); + for (APIContextAware contextAware: contextAwareMap.values()) + { + contextAware.setAPIContext(servletContext); + } + } + } diff --git a/source/java/org/alfresco/web/api/AlfWebClientAuthenticator.java b/source/java/org/alfresco/web/api/AlfWebClientAuthenticator.java new file mode 100644 index 0000000000..93aeb9672d --- /dev/null +++ b/source/java/org/alfresco/web/api/AlfWebClientAuthenticator.java @@ -0,0 +1,162 @@ +/* + * 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.api; + +import javax.servlet.ServletContext; + +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.web.app.servlet.AuthenticationHelper; +import org.alfresco.web.app.servlet.AuthenticationStatus; +import org.alfresco.web.app.servlet.BaseServlet; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +/** + * Alfresco Web Client Authentication Interceptor + * + * @author davidc + */ +public class AlfWebClientAuthenticator implements MethodInterceptor, APIContextAware +{ + // Logger + private static final Log logger = LogFactory.getLog(AlfWebClientAuthenticator.class); + + // dependencies + private ServletContext context; + private AuthenticationService authenticationService; + + + /* (non-Javadoc) + * @see org.alfresco.web.api.APIContextAware#setAPIContext(javax.servlet.ServletContext) + */ + public void setAPIContext(ServletContext context) + { + this.context = context; + } + + /** + * @param authenticationService + */ + public void setAuthenticationService(AuthenticationService authenticationService) + { + this.authenticationService = authenticationService; + } + + /* (non-Javadoc) + * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation) + */ + public Object invoke(MethodInvocation invocation) + throws Throwable + { + String currentUser = null; + Object retVal = null; + Object[] args = invocation.getArguments(); + APIRequest request = (APIRequest)args[0]; + APIResponse response = (APIResponse)args[1]; + APIService service = (APIService)invocation.getThis(); + AuthenticationStatus status = null; + + try + { + + // + // Determine if user already authenticated + // + + currentUser = AuthenticationUtil.getCurrentUserName(); + if (logger.isDebugEnabled()) + logger.debug("Current authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser)); + + // + // validate credentials + // + + String ticket = request.getParameter("ticket"); + boolean isGuest = request.isGuest(); + + if (logger.isDebugEnabled()) + { + logger.debug("Service authentication required: " + service.getRequiredAuthentication()); + logger.debug("Guest login: " + isGuest); + logger.debug("Ticket provided: " + (ticket != null && ticket.length() > 0)); + } + + if (ticket != null && ticket.length() > 0) + { + if (logger.isDebugEnabled()) + logger.debug("Authenticating ticket " + ticket); + + status = AuthenticationHelper.authenticate(context, request, response, ticket); + } + else + { + if (isGuest && service.getRequiredAuthentication() == APIRequest.RequiredAuthentication.Guest) + { + if (logger.isDebugEnabled()) + logger.debug("Authenticating as Guest"); + + status = AuthenticationHelper.authenticate(context, request, response, true); + } + else + { + if (logger.isDebugEnabled()) + logger.debug("Authenticating session"); + + status = AuthenticationHelper.authenticate(context, request, response, false); + } + } + + // + // execute API service or request authorization + // + + if (status != null && status != AuthenticationStatus.Failure) + { + retVal = invocation.proceed(); + } + else + { + // authentication failed - now need to display the login page to the user, if asked to + if (logger.isDebugEnabled()) + logger.debug("Redirecting to Alfresco Login"); + + BaseServlet.redirectToLoginPage(request, response, context); + } + } + finally + { + if (status != null && status != AuthenticationStatus.Failure) + { + authenticationService.clearCurrentSecurityContext(); + if (currentUser != null) + { + AuthenticationUtil.setCurrentUser(currentUser); + } + + if (logger.isDebugEnabled()) + logger.debug("Authentication reset: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser)); + } + } + + return retVal; + } + +} diff --git a/source/java/org/alfresco/web/api/services/APIServiceImpl.java b/source/java/org/alfresco/web/api/services/APIServiceImpl.java index 185fffbef0..b3c2c6da44 100644 --- a/source/java/org/alfresco/web/api/services/APIServiceImpl.java +++ b/source/java/org/alfresco/web/api/services/APIServiceImpl.java @@ -26,6 +26,7 @@ import javax.servlet.ServletContext; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.TemplateService; import org.alfresco.service.descriptor.DescriptorService; +import org.alfresco.web.api.APIContextAware; import org.alfresco.web.api.APIRequest; import org.alfresco.web.api.APIResponse; import org.alfresco.web.api.APIService; @@ -37,7 +38,7 @@ import org.springframework.beans.factory.BeanNameAware; * * @author davidc */ -public abstract class APIServiceImpl implements BeanNameAware, APIService +public abstract class APIServiceImpl implements BeanNameAware, APIService, APIContextAware { private String name; private String uri; @@ -60,6 +61,14 @@ public abstract class APIServiceImpl implements BeanNameAware, APIService this.name = name; } + /* (non-Javadoc) + * @see org.alfresco.web.api.APIContextAware#setAPIContext(javax.servlet.ServletContext) + */ + public void setAPIContext(ServletContext context) + { + this.context = context; + } + /** * @param serviceRegistry */ @@ -84,14 +93,6 @@ public abstract class APIServiceImpl implements BeanNameAware, APIService this.descriptorService = descriptorService; } - /* (non-Javadoc) - * @see org.alfresco.web.api.APIService#init(javax.servlet.ServletContext) - */ - public void init(ServletContext context) - { - this.context = context; - } - /** * Sets the Http URI * @@ -130,7 +131,7 @@ public abstract class APIServiceImpl implements BeanNameAware, APIService /** * @return descriptorService */ - protected ServletContext getServletContext() + protected ServletContext getAPIContext() { return context; } diff --git a/source/java/org/alfresco/web/api/services/TextSearch.java b/source/java/org/alfresco/web/api/services/TextSearch.java index 2f10e4772e..c5cfdd6c14 100644 --- a/source/java/org/alfresco/web/api/services/TextSearch.java +++ b/source/java/org/alfresco/web/api/services/TextSearch.java @@ -71,7 +71,7 @@ public class TextSearch extends APIServiceImpl { public String resolveImagePathForName(String filename, boolean small) { - return Utils.getFileTypeImage(getServletContext(), filename, small); + return Utils.getFileTypeImage(getAPIContext(), filename, small); } };