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.ServletRequest;
import javax.servlet.ServletResponse; 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 * 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. * be configured in and out according to the authentication subsystem in use.
* *
* @author dward * @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) * (non-Javadoc)
* @see org.alfresco.repo.web.filter.beans.DependencyInjectedFilter#doFilter(javax.servlet.ServletContext, * @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); 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.MD4PasswordEncoder;
import org.alfresco.repo.security.authentication.MD4PasswordEncoderImpl; import org.alfresco.repo.security.authentication.MD4PasswordEncoderImpl;
import org.alfresco.repo.security.authentication.NTLMMode; 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.alfresco.repo.security.authentication.ntlm.NTLMPassthruToken;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@@ -114,6 +115,9 @@ public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthentication
// Disable NTLMv2 support // Disable NTLMv2 support
private boolean m_disableNTLMv2 = false; 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 // Check that the authentication component supports the required mode
if (authenticationComponent.getNTLMMode() != NTLMMode.MD4_PROVIDER && if (!(authenticationComponent instanceof NLTMAuthenticator))
authenticationComponent.getNTLMMode() != NTLMMode.PASS_THROUGH) {
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"); 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, // Set the NTLM flags depending on the authentication component supporting MD4 passwords,
// or is using passthru auth // 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 // Allow the client to use an NTLMv2 logon
@@ -388,7 +397,7 @@ public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthentication
byte[] challenge = null; byte[] challenge = null;
NTLMPassthruToken authToken = null; NTLMPassthruToken authToken = null;
if (authenticationComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER) if (nltmAuthenticator.getNTLMMode() == NTLMMode.MD4_PROVIDER)
{ {
// Generate a random 8 byte challenge // Generate a random 8 byte challenge
@@ -411,7 +420,7 @@ public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthentication
authToken = new NTLMPassthruToken(domain); authToken = new NTLMPassthruToken(domain);
// Run the first stage of the passthru authentication to get the challenge // Run the first stage of the passthru authentication to get the challenge
authenticationComponent.authenticate(authToken); nltmAuthenticator.authenticate(authToken);
// Get the challenge from the token // Get the challenge from the token
if (authToken.getChallenge() != null) if (authToken.getChallenge() != null)
@@ -531,7 +540,7 @@ public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthentication
else else
{ {
// Check if we are using local MD4 password hashes or passthru authentication // 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 // Check if guest logons are allowed and this is a guest logon
if (m_allowGuest && userName.equalsIgnoreCase(authenticationComponent.getGuestUserName())) if (m_allowGuest && userName.equalsIgnoreCase(authenticationComponent.getGuestUserName()))
@@ -594,7 +603,7 @@ public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthentication
try try
{ {
// Run the second stage of the passthru authentication // Run the second stage of the passthru authentication
authenticationComponent.authenticate(authToken); nltmAuthenticator.authenticate(authToken);
authenticated = true; authenticated = true;
// Check if the user has been logged on as guest // Check if the user has been logged on as guest
@@ -1005,7 +1014,7 @@ public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthentication
tx.begin(); tx.begin();
// Get the stored MD4 hashed password for the user, or null if the user does not exist // 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) 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.jlan.util.IPAddress;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.SessionUser; 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.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException; import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
@@ -61,7 +62,7 @@ import org.springframework.beans.factory.InitializingBean;
* @author gkspencer * @author gkspencer
* @author kroast * @author kroast
*/ */
public abstract class BaseSSOAuthenticationFilter implements DependencyInjectedFilter, InitializingBean public abstract class BaseSSOAuthenticationFilter implements DependencyInjectedFilter, ActivateableBean, InitializingBean
{ {
// Constants // Constants
// //
@@ -112,6 +113,8 @@ public abstract class BaseSSOAuthenticationFilter implements DependencyInjectedF
private String m_lastConfiguredServerName; private String m_lastConfiguredServerName;
private String m_lastResolvedServerName; private String m_lastResolvedServerName;
private boolean m_isActive = true;
/** /**
* @param serverConfiguration the serverConfiguration to set * @param serverConfiguration the serverConfiguration to set
@@ -159,7 +162,27 @@ public abstract class BaseSSOAuthenticationFilter implements DependencyInjectedF
public void setTransactionService(TransactionService transactionService) public void setTransactionService(TransactionService transactionService)
{ {
this.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) /* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()