diff --git a/source/java/org/alfresco/repo/web/filter/beans/BeanProxyFilter.java b/source/java/org/alfresco/repo/web/filter/beans/BeanProxyFilter.java
new file mode 100644
index 0000000000..31747d0724
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/filter/beans/BeanProxyFilter.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have received a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.web.filter.beans;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+/**
+ * An adapter from the servlet filter world into the Spring dependency injected world. Simply looks up a
+ * {@link DependencyInjectedFilter} with a configured bean name and delegates the
+ * {@link #doFilter(ServletRequest, ServletResponse, FilterChain)} call to that. This allows us to swap in and out
+ * different implementations for different 'hook points' in web.xml.
+ *
+ * @author dward
+ */
+public class BeanProxyFilter implements Filter
+{
+ /**
+ * Name of the init parameter that carries the proxied bean name
+ */
+ private static final String INIT_PARAM_BEAN_NAME = "beanName";
+
+ private DependencyInjectedFilter filter;
+ private ServletContext context;
+
+ /**
+ * Initialize the filter.
+ *
+ * @param args
+ * FilterConfig
+ * @throws ServletException
+ * the servlet exception
+ * @exception ServletException
+ */
+ public void init(FilterConfig args) throws ServletException
+ {
+ WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(args.getServletContext());
+ this.filter = (DependencyInjectedFilter)ctx.getBean(args.getInitParameter(INIT_PARAM_BEAN_NAME));
+ this.context = args.getServletContext();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.servlet.Filter#destroy()
+ */
+ public void destroy()
+ {
+ this.filter = null;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
+ */
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
+ ServletException
+ {
+ this.filter.doFilter(this.context, request, response, chain);
+ }
+}
diff --git a/source/java/org/alfresco/repo/web/filter/beans/DependencyInjectedFilter.java b/source/java/org/alfresco/repo/web/filter/beans/DependencyInjectedFilter.java
new file mode 100644
index 0000000000..033a6935d8
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/filter/beans/DependencyInjectedFilter.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have received a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.web.filter.beans;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+/**
+ * A bean-like equivalent of a servlet filter, designed to be managed by a Spring container.
+ *
+ * @see BeanProxyFilter
+ * @author dward
+ */
+public interface DependencyInjectedFilter
+{
+ /**
+ * The doFilter
method of the Filter is called by the container each time a request/response pair is
+ * passed through the chain due to a client request for a resource at the end of the chain. The FilterChain passed
+ * in to this method allows the Filter to pass on the request and response to the next entity in the chain.
+ *
+ * A typical implementation of this method would follow the following pattern:-
+ * 1. Examine the request
+ * 2. Optionally wrap the request object with a custom implementation to filter content or headers for input
+ * filtering
+ * 3. Optionally wrap the response object with a custom implementation to filter content or headers for output
+ * filtering
+ * 4. a) Either invoke the next entity in the chain using the FilterChain object (
+ * chain.doFilter()
),
+ * 4. b) or not pass on the request/response pair to the next entity in the filter chain to block
+ * the request processing
+ * 5. Directly set headers on the response after invocation of the next entity in the filter chain.
+ **/
+ public void doFilter(ServletContext context, ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
+ ServletException;
+}
diff --git a/source/java/org/alfresco/repo/web/filter/beans/NullFilter.java b/source/java/org/alfresco/repo/web/filter/beans/NullFilter.java
new file mode 100644
index 0000000000..e1f12e0a5f
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/filter/beans/NullFilter.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have received a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.web.filter.beans;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+/**
+ * A Benign filter that does nothing more than invoke the filter chain. Allows strategic points of the filter chain to
+ * be configured in and out according to the authentication subsystem in use.
+ *
+ * @author dward
+ */
+public class NullFilter implements DependencyInjectedFilter
+{
+ /*
+ * (non-Javadoc)
+ * @see org.alfresco.repo.web.filter.beans.DependencyInjectedFilter#doFilter(javax.servlet.ServletContext,
+ * javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
+ */
+ public void doFilter(ServletContext context, ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException
+ {
+ chain.doFilter(request, response);
+ }
+}
diff --git a/source/java/org/alfresco/repo/webdav/WebDAVServlet.java b/source/java/org/alfresco/repo/webdav/WebDAVServlet.java
index 358677b02f..796548b8ea 100644
--- a/source/java/org/alfresco/repo/webdav/WebDAVServlet.java
+++ b/source/java/org/alfresco/repo/webdav/WebDAVServlet.java
@@ -258,10 +258,16 @@ public class WebDAVServlet extends HttpServlet
public void init(ServletConfig config) throws ServletException
{
super.init(config);
+
+ // Get service registry
+ WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
- // Get service registry
-
- WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
+ // If no context has been initialised, exit silently so config changes can be made
+ if (context == null)
+ {
+ return;
+ }
+
m_serviceRegistry = (ServiceRegistry)context.getBean(ServiceRegistry.SERVICE_REGISTRY);
m_transactionService = m_serviceRegistry.getTransactionService();
diff --git a/source/java/org/alfresco/repo/webdav/auth/AuthenticationFilter.java b/source/java/org/alfresco/repo/webdav/auth/AuthenticationFilter.java
index 88bdfa9035..d856970bbc 100644
--- a/source/java/org/alfresco/repo/webdav/auth/AuthenticationFilter.java
+++ b/source/java/org/alfresco/repo/webdav/auth/AuthenticationFilter.java
@@ -27,9 +27,7 @@ package org.alfresco.repo.webdav.auth;
import java.io.IOException;
-import javax.servlet.Filter;
import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
@@ -40,7 +38,7 @@ import javax.transaction.UserTransaction;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationException;
-import org.alfresco.service.ServiceRegistry;
+import org.alfresco.repo.web.filter.beans.DependencyInjectedFilter;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
@@ -51,15 +49,13 @@ import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.springframework.web.context.WebApplicationContext;
-import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* WebDAV Authentication Filter Class
*
* @author GKSpencer
*/
-public class AuthenticationFilter implements Filter
+public class AuthenticationFilter implements DependencyInjectedFilter
{
// Debug logging
@@ -75,51 +71,58 @@ public class AuthenticationFilter implements Filter
private static final String PPT_EXTN = ".ppt";
private static final String VTI_IGNORE = "&vtiIgnore";
- // Servlet context
-
- private ServletContext m_context;
-
// Various services required by NTLM authenticator
- private AuthenticationService m_authService;
- private PersonService m_personService;
- private NodeService m_nodeService;
- private TransactionService m_transactionService;
+ private AuthenticationService authService;
+ private PersonService personService;
+ private NodeService nodeService;
+ private TransactionService transactionService;
+
/**
- * Initialize the filter
- *
- * @param config FitlerConfig
- * @exception ServletException
+ * @param authService the authService to set
*/
- public void init(FilterConfig config) throws ServletException
+ public void setAuthenticationService(AuthenticationService authService)
{
- // Save the context
+ this.authService = authService;
+ }
- m_context = config.getServletContext();
+ /**
+ * @param personService the personService to set
+ */
+ public void setPersonService(PersonService personService)
+ {
+ this.personService = personService;
+ }
- // Setup the authentication context
+ /**
+ * @param nodeService the nodeService to set
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
- WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(m_context);
-
- ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
- m_nodeService = serviceRegistry.getNodeService();
- m_authService = serviceRegistry.getAuthenticationService();
- m_transactionService = serviceRegistry.getTransactionService();
- m_personService = (PersonService) ctx.getBean("PersonService"); // transactional and permission-checked
+ /**
+ * @param transactionService the transactionService to set
+ */
+ public void setTransactionService(TransactionService transactionService)
+ {
+ this.transactionService = transactionService;
}
/**
* Run the authentication filter
*
+ * @param context ServletContext
* @param req ServletRequest
* @param resp ServletResponse
* @param chain FilterChain
* @exception ServletException
* @exception IOException
*/
- public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException,
- ServletException
+ public void doFilter(ServletContext context, ServletRequest req, ServletResponse resp, FilterChain chain)
+ throws IOException, ServletException
{
// Assume it's an HTTP request
@@ -163,19 +166,19 @@ public class AuthenticationFilter implements Filter
{
// Authenticate the user
- m_authService.authenticate(username, password.toCharArray());
+ authService.authenticate(username, password.toCharArray());
// Set the user name as stored by the back end
- username = m_authService.getCurrentUserName();
+ username = authService.getCurrentUserName();
// Get the user node and home folder
- NodeRef personNodeRef = m_personService.getPerson(username);
- NodeRef homeSpaceRef = (NodeRef) m_nodeService.getProperty(personNodeRef, ContentModel.PROP_HOMEFOLDER);
+ NodeRef personNodeRef = personService.getPerson(username);
+ NodeRef homeSpaceRef = (NodeRef) nodeService.getProperty(personNodeRef, ContentModel.PROP_HOMEFOLDER);
// Setup User object and Home space ID etc.
- user = new WebDAVUser(username, m_authService.getCurrentTicket(), homeSpaceRef);
+ user = new WebDAVUser(username, authService.getCurrentTicket(), homeSpaceRef);
httpReq.getSession().setAttribute(AUTHENTICATION_USER, user);
}
@@ -213,24 +216,24 @@ public class AuthenticationFilter implements Filter
{
// Validate the ticket
- m_authService.validate(ticket);
+ authService.validate(ticket);
// Need to create the User instance if not already available
- String currentUsername = m_authService.getCurrentUserName();
+ String currentUsername = authService.getCurrentUserName();
// Start a transaction
- tx = m_transactionService.getUserTransaction();
+ tx = transactionService.getUserTransaction();
tx.begin();
- NodeRef personRef = m_personService.getPerson(currentUsername);
- user = new WebDAVUser( currentUsername, m_authService.getCurrentTicket(), personRef);
- NodeRef homeRef = (NodeRef) m_nodeService.getProperty(personRef, ContentModel.PROP_HOMEFOLDER);
+ NodeRef personRef = personService.getPerson(currentUsername);
+ user = new WebDAVUser( currentUsername, authService.getCurrentTicket(), personRef);
+ NodeRef homeRef = (NodeRef) nodeService.getProperty(personRef, ContentModel.PROP_HOMEFOLDER);
// Check that the home space node exists - else Login cannot proceed
- if (m_nodeService.exists(homeRef) == false)
+ if (nodeService.exists(homeRef) == false)
{
throw new InvalidNodeRefException(homeRef);
}
@@ -289,7 +292,7 @@ public class AuthenticationFilter implements Filter
try
{
// Setup the authentication context
- m_authService.validate(user.getTicket());
+ authService.validate(user.getTicket());
// Set the current locale
diff --git a/source/java/org/alfresco/repo/webdav/auth/BaseKerberosAuthenticationFilter.java b/source/java/org/alfresco/repo/webdav/auth/BaseKerberosAuthenticationFilter.java
index 7f30605acf..5423206630 100644
--- a/source/java/org/alfresco/repo/webdav/auth/BaseKerberosAuthenticationFilter.java
+++ b/source/java/org/alfresco/repo/webdav/auth/BaseKerberosAuthenticationFilter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2008 Alfresco Software Limited.
+ * Copyright (C) 2006-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -41,7 +41,7 @@ import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.security.sasl.RealmCallback;
import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
@@ -84,10 +84,9 @@ public abstract class BaseKerberosAuthenticationFilter extends BaseSSOAuthentica
private String m_accountName;
private String m_password;
- // Kerberos realm and KDC address
+ // Kerberos realm
private String m_krbRealm;
- private String m_krbKDC;
// Login configuration entry name
@@ -96,180 +95,163 @@ public abstract class BaseKerberosAuthenticationFilter extends BaseSSOAuthentica
// Server login context
private LoginContext m_loginContext;
-
- // SPNEGO NegTokenInit blob, sent to the client in the SMB negotiate response
-
- private byte[] m_negTokenInit;
-
+
/**
- * Initialize the filter
+ * Sets the HTTP service account password. (the Principal should be configured in java.login.config)
*
- * @param args FilterConfig
- * @exception ServletException
+ * @param password
+ * the password to set
*/
- public void init(FilterConfig args) throws ServletException
+ public void setPassword(String password)
{
- // Call the base SSO filter initialization
+ this.m_password = password;
+ }
- super.init( args);
+ /**
+ * Sets the HTTP service account realm.
+ *
+ * @param realm the realm to set
+ */
+ public void setRealm(String realm)
+ {
+ m_krbRealm = realm;
+ }
- // Check if Kerberos is enabled, get the Kerberos KDC address
+ /**
+ * Sets the HTTP service login configuration entry name. The default is "AlfrescoHTTP"
.
+ *
+ * @param loginEntryName
+ * the loginEntryName to set
+ */
+ public void setJaasConfigEntryName(String jaasConfigEntryName)
+ {
+ m_loginEntryName = jaasConfigEntryName;
+ }
- String kdcAddress = args.getInitParameter("KDC");
-
- if (kdcAddress != null && kdcAddress.length() > 0)
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.web.filter.beans.BaseSSOAuthenticationFilter#afterPropertiesSet()
+ */
+ @Override
+ public void afterPropertiesSet() throws Exception
+ {
+ super.afterPropertiesSet();
+
+ if ( m_krbRealm == null)
{
- // Set the Kerberos KDC address
-
- m_krbKDC = kdcAddress;
+ throw new ServletException("Kerberos realm not specified");
+ }
- // Get the Kerberos realm
+ if ( m_password == null)
+ {
+ throw new ServletException("HTTP service account password not specified");
+ }
+
+ if (m_loginEntryName == null)
+ {
+ throw new ServletException("Invalid login entry specified");
+ }
+
+ // Get the local host name
+ String localName = null;
+
+ try
+ {
+ localName = InetAddress.getLocalHost().getCanonicalHostName();
+ }
+ catch ( UnknownHostException ex)
+ {
+ throw new ServletException( "Failed to get local host name");
+ }
+
+ // Create a login context for the HTTP server service
+
+ try
+ {
+ // Login the HTTP server service
- String krbRealm = args.getInitParameter("Realm");
- if ( krbRealm != null && krbRealm.length() > 0)
- {
- // Set the Kerberos realm
-
- m_krbRealm = krbRealm;
- }
- else
- throw new ServletException("Kerberos realm not specified");
-
- // Get the HTTP service account password
-
- String srvPassword = args.getInitParameter("Password");
- if ( srvPassword != null && srvPassword.length() > 0)
- {
- // Set the HTTP service account password
-
- m_password = srvPassword;
- }
- else
- throw new ServletException("HTTP service account password not specified");
-
- // Get the login configuration entry name
-
- String loginEntry = args.getInitParameter("LoginEntry");
-
- if ( loginEntry != null)
- {
- if ( loginEntry.length() > 0)
- {
- // Set the login configuration entry name to use
-
- m_loginEntryName = loginEntry;
- }
- else
- throw new ServletException("Invalid login entry specified");
- }
-
- // Get the local host name
-
- String localName = null;
-
- try
- {
- localName = InetAddress.getLocalHost().getCanonicalHostName();
- }
- catch ( UnknownHostException ex)
- {
- throw new ServletException( "Failed to get local host name");
- }
-
- // Create a login context for the HTTP server service
-
- try
- {
- // Login the HTTP server service
-
- m_loginContext = new LoginContext( m_loginEntryName, this);
- m_loginContext.login();
-
- // DEBUG
-
- if ( getLogger().isDebugEnabled())
- getLogger().debug( "HTTP Kerberos login successful");
- }
- catch ( LoginException ex)
- {
- // Debug
-
- if ( getLogger().isErrorEnabled())
- getLogger().error("HTTP Kerberos web filter error", ex);
-
- throw new ServletException("Failed to login HTTP server service");
- }
-
- // Get the HTTP service account name from the subject
-
- Subject subj = m_loginContext.getSubject();
- Principal princ = subj.getPrincipals().iterator().next();
-
- m_accountName = princ.getName();
+ m_loginContext = new LoginContext( m_loginEntryName, this);
+ m_loginContext.login();
// DEBUG
if ( getLogger().isDebugEnabled())
- getLogger().debug("Logged on using principal " + m_accountName);
+ getLogger().debug( "HTTP Kerberos login successful");
+ }
+ catch ( LoginException ex)
+ {
+ // Debug
- // Create the Oid list for the SPNEGO NegTokenInit, include NTLMSSP for fallback
+ if ( getLogger().isErrorEnabled())
+ getLogger().error("HTTP Kerberos web filter error", ex);
- Vector