Refactor subsystems for authentication chaining

- An authentication chain of size 1 configured by default
- DefaultChildApplicationContextManager supports dynamic configuration of the authentication chain via Spring or JMX. Any number of instances of any type allowed in chain.
- SubsystemChainingAuthenticationComponent and SubsystemChainingAuthenticationService iterate across configured chain for Authentication
- SSO (NTLM / Kerberos) and CIFS authentication independently activatable for any component in chain (where supported).
- SubsystemChainingProxyFactory used to proxy directly to first active CIFS authenticator or SSO filter in the chain
- CIFS server knows not to bother starting if authentication chain doesn't have an active CIFS authenticator (e.g. LDAP only)
- Rationalization of subsystem configuration folder structure and JMX object naming
- Classpath based extension mechanism for community edition - alfresco/extension/subsystems/<category>/<typeName>/<id>/*.properties in classpath can be used to configure specific subsystem instances
- Simplification of JMX infrastructure. No longer Spring bean definition based, thus allowing dynamic creation/registration of new instances at runtime.
- New AuthenticationChainTest unit test

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@14030 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Dave Ward
2009-04-21 13:29:08 +00:00
parent 814a730155
commit 01f5a926bf
3 changed files with 68 additions and 11 deletions

View File

@@ -32,14 +32,37 @@ import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.alfresco.repo.management.subsystems.ActivateableBean;
/**
* 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
public class NullFilter implements DependencyInjectedFilter, ActivateableBean
{
private boolean isActive = true;
/**
* Activates or deactivates the bean
*
* @param active
* <code>true</code> if the bean is active and initialization should complete
*/
public void setActive(boolean active)
{
this.isActive = active;
}
/* (non-Javadoc)
* @see org.alfresco.repo.management.subsystems.ActivateableBean#isActive()
*/
public boolean isActive()
{
return this.isActive;
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.web.filter.beans.DependencyInjectedFilter#doFilter(javax.servlet.ServletContext,
@@ -50,4 +73,6 @@ public class NullFilter implements DependencyInjectedFilter
{
chain.doFilter(request, response);
}
}

View File

@@ -60,6 +60,7 @@ import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.MD4PasswordEncoder;
import org.alfresco.repo.security.authentication.MD4PasswordEncoderImpl;
import org.alfresco.repo.security.authentication.NTLMMode;
import org.alfresco.repo.security.authentication.ntlm.NLTMAuthenticator;
import org.alfresco.repo.security.authentication.ntlm.NTLMPassthruToken;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
@@ -114,6 +115,9 @@ public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthentication
// Disable NTLMv2 support
private boolean m_disableNTLMv2 = false;
// SSO enabled authentication component (required)
private NLTMAuthenticator nltmAuthenticator;
/**
@@ -135,8 +139,13 @@ public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthentication
// Check that the authentication component supports the required mode
if (authenticationComponent.getNTLMMode() != NTLMMode.MD4_PROVIDER &&
authenticationComponent.getNTLMMode() != NTLMMode.PASS_THROUGH)
if (!(authenticationComponent instanceof NLTMAuthenticator))
{
throw new ServletException("Authentication component does not support NTLM");
}
this.nltmAuthenticator = (NLTMAuthenticator)this.authenticationComponent;
if (nltmAuthenticator.getNTLMMode() != NTLMMode.MD4_PROVIDER &&
nltmAuthenticator.getNTLMMode() != NTLMMode.PASS_THROUGH)
{
throw new ServletException("Required authentication mode not available");
}
@@ -154,7 +163,7 @@ public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthentication
// Set the NTLM flags depending on the authentication component supporting MD4 passwords,
// or is using passthru auth
if (authenticationComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER && m_disableNTLMv2 == false)
if (nltmAuthenticator.getNTLMMode() == NTLMMode.MD4_PROVIDER && m_disableNTLMv2 == false)
{
// Allow the client to use an NTLMv2 logon
@@ -388,7 +397,7 @@ public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthentication
byte[] challenge = null;
NTLMPassthruToken authToken = null;
if (authenticationComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
if (nltmAuthenticator.getNTLMMode() == NTLMMode.MD4_PROVIDER)
{
// Generate a random 8 byte challenge
@@ -411,7 +420,7 @@ public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthentication
authToken = new NTLMPassthruToken(domain);
// Run the first stage of the passthru authentication to get the challenge
authenticationComponent.authenticate(authToken);
nltmAuthenticator.authenticate(authToken);
// Get the challenge from the token
if (authToken.getChallenge() != null)
@@ -531,7 +540,7 @@ public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthentication
else
{
// Check if we are using local MD4 password hashes or passthru authentication
if (authenticationComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
if (nltmAuthenticator.getNTLMMode() == NTLMMode.MD4_PROVIDER)
{
// Check if guest logons are allowed and this is a guest logon
if (m_allowGuest && userName.equalsIgnoreCase(authenticationComponent.getGuestUserName()))
@@ -594,7 +603,7 @@ public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthentication
try
{
// Run the second stage of the passthru authentication
authenticationComponent.authenticate(authToken);
nltmAuthenticator.authenticate(authToken);
authenticated = true;
// Check if the user has been logged on as guest
@@ -1005,7 +1014,7 @@ public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthentication
tx.begin();
// Get the stored MD4 hashed password for the user, or null if the user does not exist
md4hash = authenticationComponent.getMD4HashedPassword(userName);
md4hash = nltmAuthenticator.getMD4HashedPassword(userName);
}
catch (Throwable ex)
{

View File

@@ -42,6 +42,7 @@ import org.alfresco.jlan.server.config.SecurityConfigSection;
import org.alfresco.jlan.util.IPAddress;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.SessionUser;
import org.alfresco.repo.management.subsystems.ActivateableBean;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
@@ -61,7 +62,7 @@ import org.springframework.beans.factory.InitializingBean;
* @author gkspencer
* @author kroast
*/
public abstract class BaseSSOAuthenticationFilter implements DependencyInjectedFilter, InitializingBean
public abstract class BaseSSOAuthenticationFilter implements DependencyInjectedFilter, ActivateableBean, InitializingBean
{
// Constants
//
@@ -112,6 +113,8 @@ public abstract class BaseSSOAuthenticationFilter implements DependencyInjectedF
private String m_lastConfiguredServerName;
private String m_lastResolvedServerName;
private boolean m_isActive = true;
/**
* @param serverConfiguration the serverConfiguration to set
@@ -159,7 +162,27 @@ public abstract class BaseSSOAuthenticationFilter implements DependencyInjectedF
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
}
}
/**
* Activates or deactivates the bean
*
* @param active
* <code>true</code> if the bean is active and initialization should complete
*/
public void setActive(boolean active)
{
this.m_isActive = active;
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.management.subsystems.ActivateableBean#isActive()
*/
public boolean isActive()
{
return m_isActive;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()