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 bf949d306b
commit d2180c5eaa
77 changed files with 3556 additions and 1371 deletions

View File

@@ -415,30 +415,6 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
authenticationContext.clearCurrentSecurityContext();
}
/**
* The default is not to support Authentication token base authentication
*/
public Authentication authenticate(Authentication token) throws AuthenticationException
{
throw new AlfrescoRuntimeException("Authentication via token not supported");
}
/**
* The should only be supported if getNTLMMode() is NTLMMode.MD4_PROVIDER.
*/
public String getMD4HashedPassword(String userName)
{
throw new UnsupportedOperationException();
}
/**
* Get the NTML mode - none - supports MD4 hash to integrate - or it can asct as an NTLM authentication
*/
public NTLMMode getNTLMMode()
{
return NTLMMode.NONE;
}
class SetCurrentUserCallback implements RetryingTransactionHelper.RetryingTransactionCallback<Authentication>
{
AuthenticationException ae = null;
@@ -527,7 +503,7 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
*
* @param defaultAdministratorUserNames
*/
public void setDefaultAdministratorUserNames(String defaultAdministratorUserNames)
public void setDefaultAdministratorUserNameList(String defaultAdministratorUserNames)
{
Set<String> nameSet = new TreeSet<String>();
if (defaultAdministratorUserNames.length() > 0)

View File

@@ -28,7 +28,6 @@ import java.util.List;
import java.util.Set;
import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.service.Managed;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.springframework.beans.factory.InitializingBean;
@@ -57,6 +56,7 @@ public abstract class AbstractAuthenticationService implements AuthenticationSer
this.sysAdminCache = sysAdminCache;
}
@SuppressWarnings("unchecked")
public void preAuthenticationCheck(String userName) throws AuthenticationException
{
if (sysAdminCache != null)
@@ -77,7 +77,6 @@ public abstract class AbstractAuthenticationService implements AuthenticationSer
}
}
@Managed(category="Security")
public void setAllowedUsers(List<String> allowedUsers)
{
if (initialised)
@@ -107,7 +106,6 @@ public abstract class AbstractAuthenticationService implements AuthenticationSer
}
}
@Managed(category="Security")
public void setMaxUsers(int maxUsers)
{
if (initialised)

View File

@@ -0,0 +1,162 @@
/*
* 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.security.authentication;
import java.util.Collection;
import java.util.Set;
import java.util.TreeSet;
import net.sf.acegisecurity.Authentication;
/**
* A base class for chaining authentication components. Where appropriate, methods will 'chain' across multiple
* {@link AuthenticationComponent} instances, as returned by {@link #getUsableAuthenticationComponents()}.
*
* @author dward
*/
public abstract class AbstractChainingAuthenticationComponent extends AbstractAuthenticationComponent
{
/**
* Instantiates a new abstract chaining authentication component.
*/
public AbstractChainingAuthenticationComponent()
{
super();
}
/**
* Gets the authentication components across which methods will chain.
*
* @return the usable authentication components
*/
protected abstract Collection<AuthenticationComponent> getUsableAuthenticationComponents();
/**
* Chain authentication with user name and password - tries all in order until one works, or fails.
*
* @param userName
* the user name
* @param password
* the password
*/
@Override
protected void authenticateImpl(String userName, char[] password)
{
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
try
{
authComponent.authenticate(userName, password);
return;
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Failed to authenticate");
}
/**
* If any implementation supports guest then guest is allowed.
*
* @return true, if implementation allows guest login
*/
@Override
protected boolean implementationAllowsGuestLogin()
{
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
if (authComponent.guestUserAuthenticationAllowed())
{
return true;
}
}
return false;
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.security.authentication.AbstractAuthenticationComponent#setCurrentUser(java.lang.String,
* org.alfresco.repo.security.authentication.AuthenticationComponent.UserNameValidationMode)
*/
@Override
public Authentication setCurrentUser(String userName, UserNameValidationMode validationMode)
{
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
try
{
return authComponent.setCurrentUser(userName, validationMode);
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Failed to set current user " + userName);
}
/**
* Set the current user - try all implementations - as some may check the user exists.
*
* @param userName
* the user name
* @return the authentication
*/
@Override
public Authentication setCurrentUser(String userName)
{
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
try
{
return authComponent.setCurrentUser(userName);
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Failed to set current user " + userName);
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.security.authentication.AbstractAuthenticationComponent#getDefaultAdministratorUserNames()
*/
@Override
public Set<String> getDefaultAdministratorUserNames()
{
Set<String> defaultAdministratorUserNames = new TreeSet<String>();
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
defaultAdministratorUserNames.addAll(authComponent.getDefaultAdministratorUserNames());
}
return defaultAdministratorUserNames;
}
}

View File

@@ -0,0 +1,521 @@
/*
* 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.security.authentication;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.PermissionService;
/**
* A base class for chaining authentication services. Where appropriate, methods will 'chain' across multiple
* {@link AuthenticationService} instances, as returned by {@link #getUsableAuthenticationServices()}.
*
* @author dward
*/
public abstract class AbstractChainingAuthenticationService extends AbstractAuthenticationService
{
/**
* Instantiates a new abstract chaining authentication service.
*/
public AbstractChainingAuthenticationService()
{
super();
}
/**
* Gets the mutable authentication service.
*
* @return the mutable authentication service
*/
public abstract AuthenticationService getMutableAuthenticationService();
/**
* Gets the authentication services across which methods will chain.
*
* @return the usable authentication services
*/
protected abstract List<AuthenticationService> getUsableAuthenticationServices();
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#createAuthentication(java.lang.String, char[])
*/
public void createAuthentication(String userName, char[] password) throws AuthenticationException
{
if (getMutableAuthenticationService() == null)
{
throw new AuthenticationException(
"Unable to create authentication as there is no suitable authentication service.");
}
getMutableAuthenticationService().createAuthentication(userName, password);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#updateAuthentication(java.lang.String, char[], char[])
*/
public void updateAuthentication(String userName, char[] oldPassword, char[] newPassword)
throws AuthenticationException
{
if (getMutableAuthenticationService() == null)
{
throw new AuthenticationException(
"Unable to update authentication as there is no suitable authentication service.");
}
getMutableAuthenticationService().updateAuthentication(userName, oldPassword, newPassword);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#setAuthentication(java.lang.String, char[])
*/
public void setAuthentication(String userName, char[] newPassword) throws AuthenticationException
{
if (getMutableAuthenticationService() == null)
{
throw new AuthenticationException(
"Unable to set authentication as there is no suitable authentication service.");
}
getMutableAuthenticationService().setAuthentication(userName, newPassword);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#deleteAuthentication(java.lang.String)
*/
public void deleteAuthentication(String userName) throws AuthenticationException
{
if (getMutableAuthenticationService() == null)
{
throw new AuthenticationException(
"Unable to delete authentication as there is no suitable authentication service.");
}
getMutableAuthenticationService().deleteAuthentication(userName);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#setAuthenticationEnabled(java.lang.String, boolean)
*/
public void setAuthenticationEnabled(String userName, boolean enabled) throws AuthenticationException
{
if (getMutableAuthenticationService() == null)
{
throw new AuthenticationException(
"Unable to set authentication enabled as there is no suitable authentication service.");
}
getMutableAuthenticationService().setAuthenticationEnabled(userName, enabled);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#getAuthenticationEnabled(java.lang.String)
*/
public boolean getAuthenticationEnabled(String userName) throws AuthenticationException
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
if (authService.getAuthenticationEnabled(userName))
{
return true;
}
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
return false;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#authenticate(java.lang.String, char[])
*/
public void authenticate(String userName, char[] password) throws AuthenticationException
{
preAuthenticationCheck(userName);
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
authService.authenticate(userName, password);
return;
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Failed to authenticate");
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#authenticateAsGuest()
*/
public void authenticateAsGuest() throws AuthenticationException
{
preAuthenticationCheck(PermissionService.GUEST_AUTHORITY);
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
authService.authenticateAsGuest();
return;
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Guest authentication not supported");
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#guestUserAuthenticationAllowed()
*/
public boolean guestUserAuthenticationAllowed()
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
if (authService.guestUserAuthenticationAllowed())
{
return true;
}
}
// it isn't allowed in any of the authentication components
return false;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#authenticationExists(java.lang.String)
*/
public boolean authenticationExists(String userName)
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
if (authService.authenticationExists(userName))
{
return true;
}
}
// it doesn't exist in any of the authentication components
return false;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#getCurrentUserName()
*/
public String getCurrentUserName() throws AuthenticationException
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
return authService.getCurrentUserName();
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
return null;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#invalidateUserSession(java.lang.String)
*/
public void invalidateUserSession(String userName) throws AuthenticationException
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
authService.invalidateUserSession(userName);
return;
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Unable to invalidate user session");
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#invalidateTicket(java.lang.String)
*/
public void invalidateTicket(String ticket) throws AuthenticationException
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
authService.invalidateTicket(ticket);
return;
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Unable to invalidate ticket");
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#validate(java.lang.String)
*/
public void validate(String ticket) throws AuthenticationException
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
authService.validate(ticket);
return;
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Unable to validate ticket");
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#getCurrentTicket()
*/
public String getCurrentTicket()
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
return authService.getCurrentTicket();
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
return null;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#getNewTicket()
*/
public String getNewTicket()
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
return authService.getNewTicket();
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
return null;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#clearCurrentSecurityContext()
*/
public void clearCurrentSecurityContext()
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
authService.clearCurrentSecurityContext();
return;
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Failed to clear security context");
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#isCurrentUserTheSystemUser()
*/
public boolean isCurrentUserTheSystemUser()
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
return authService.isCurrentUserTheSystemUser();
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
return false;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#getDomains()
*/
public Set<String> getDomains()
{
HashSet<String> domains = new HashSet<String>();
for (AuthenticationService authService : getUsableAuthenticationServices())
{
domains.addAll(authService.getDomains());
}
return domains;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#getDomainsThatAllowUserCreation()
*/
public Set<String> getDomainsThatAllowUserCreation()
{
HashSet<String> domains = new HashSet<String>();
if (getMutableAuthenticationService() != null)
{
domains.addAll(getMutableAuthenticationService().getDomainsThatAllowUserCreation());
}
return domains;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#getDomainsThatAllowUserDeletion()
*/
public Set<String> getDomainsThatAllowUserDeletion()
{
HashSet<String> domains = new HashSet<String>();
if (getMutableAuthenticationService() != null)
{
domains.addAll(getMutableAuthenticationService().getDomainsThatAllowUserDeletion());
}
return domains;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#getDomiansThatAllowUserPasswordChanges()
*/
public Set<String> getDomiansThatAllowUserPasswordChanges()
{
HashSet<String> domains = new HashSet<String>();
if (getMutableAuthenticationService() != null)
{
domains.addAll(getMutableAuthenticationService().getDomiansThatAllowUserPasswordChanges());
}
return domains;
}
/* (non-Javadoc)
* @see org.alfresco.repo.security.authentication.AbstractAuthenticationService#getUsersWithTickets(boolean)
*/
@Override
public Set<String> getUsersWithTickets(boolean nonExpiredOnly)
{
HashSet<String> users = new HashSet<String>();
for (AuthenticationService authService : getUsableAuthenticationServices())
{
if (authService instanceof AbstractAuthenticationService)
{
users.addAll(((AbstractAuthenticationService) authService).getUsersWithTickets(nonExpiredOnly));
}
}
return users;
}
/* (non-Javadoc)
* @see org.alfresco.repo.security.authentication.AbstractAuthenticationService#countTickets(boolean)
*/
@Override
public int countTickets(boolean nonExpiredOnly)
{
int count = 0;
for (TicketComponent tc : getTicketComponents())
{
count += tc.countTickets(nonExpiredOnly);
}
return count;
}
/* (non-Javadoc)
* @see org.alfresco.repo.security.authentication.AbstractAuthenticationService#invalidateTickets(boolean)
*/
@Override
public int invalidateTickets(boolean nonExpiredOnly)
{
int count = 0;
for (AuthenticationService authService : getUsableAuthenticationServices())
{
if (authService instanceof AbstractAuthenticationService)
{
count += ((AbstractAuthenticationService) authService).invalidateTickets(nonExpiredOnly);
}
}
return count;
}
/* (non-Javadoc)
* @see org.alfresco.repo.security.authentication.AbstractAuthenticationService#getTicketComponents()
*/
@Override
public Set<TicketComponent> getTicketComponents()
{
Set<TicketComponent> tcs = new HashSet<TicketComponent>();
for (AuthenticationService authService : getUsableAuthenticationServices())
{
if (authService instanceof AbstractAuthenticationService)
{
tcs.addAll(((AbstractAuthenticationService) authService).getTicketComponents());
}
}
return tcs;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.security.AuthenticationService#getDefaultAdministratorUserNames()
*/
public Set<String> getDefaultAdministratorUserNames()
{
Set<String> defaultAdministratorUserNames = new TreeSet<String>();
for (AuthenticationService authService : getUsableAuthenticationServices())
{
defaultAdministratorUserNames.addAll(authService.getDefaultAdministratorUserNames());
}
return defaultAdministratorUserNames;
}
}

View File

@@ -41,15 +41,6 @@ public interface AuthenticationComponent extends AuthenticationContext
* @throws AuthenticationException
*/
public void authenticate(String userName, char[] password) throws AuthenticationException;
/**
* Authenticate using a token
*
* @param token Authentication
* @return Authentication
* @throws AuthenticationException
*/
public Authentication authenticate(Authentication token) throws AuthenticationException;
/**
* Explicitly set the current user to be authenticated.
@@ -76,16 +67,6 @@ public interface AuthenticationComponent extends AuthenticationContext
*/
public boolean guestUserAuthenticationAllowed();
/**
* Get the enum that describes NTLM integration
*/
public NTLMMode getNTLMMode();
/**
* Get the MD4 password hash, as required by NTLM based authentication methods.
*/
public String getMD4HashedPassword(String userName);
/**
* Gets a set of user names who for this particular authentication system should be considered administrators by
* default. If the security framework is case sensitive these values should be case sensitive user names. If the

View File

@@ -29,13 +29,15 @@ import java.io.StringWriter;
import java.util.Collections;
import java.util.Set;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.AuthenticationManager;
import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.alfresco.service.Managed;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.security.authentication.ntlm.NLTMAuthenticator;
public class AuthenticationComponentImpl extends AbstractAuthenticationComponent
public class AuthenticationComponentImpl extends AbstractAuthenticationComponent implements NLTMAuthenticator
{
private MutableAuthenticationDao authenticationDao;
@@ -61,7 +63,6 @@ public class AuthenticationComponentImpl extends AbstractAuthenticationComponent
*
* @param authenticationDao
*/
@Managed(category = "Security")
public void setAuthenticationDao(MutableAuthenticationDao authenticationDao)
{
this.authenticationDao = authenticationDao;
@@ -107,16 +108,22 @@ public class AuthenticationComponentImpl extends AbstractAuthenticationComponent
/**
* Get the password hash from the DAO
*/
@Override
public String getMD4HashedPassword(String userName)
{
return this.authenticationDao.getMD4HashedPassword(userName);
}
/**
* The default is not to support Authentication token base authentication
*/
public Authentication authenticate(Authentication token) throws AuthenticationException
{
throw new AlfrescoRuntimeException("Authentication via token not supported");
}
/**
* This implementation supported MD4 password hashes.
*/
@Override
public NTLMMode getNTLMMode()
{
return NTLMMode.MD4_PROVIDER;

View File

@@ -28,7 +28,6 @@ import java.util.Collections;
import java.util.Set;
import org.alfresco.repo.security.authentication.AuthenticationComponent.UserNameValidationMode;
import org.alfresco.service.Managed;
import org.alfresco.service.cmr.security.PermissionService;
public class AuthenticationServiceImpl extends AbstractAuthenticationService
@@ -52,7 +51,6 @@ public class AuthenticationServiceImpl extends AbstractAuthenticationService
super();
}
@Managed(category="Security")
public void setAuthenticationDao(MutableAuthenticationDao authenticationDao)
{
this.authenticationDao = authenticationDao;
@@ -63,7 +61,6 @@ public class AuthenticationServiceImpl extends AbstractAuthenticationService
this.ticketComponent = ticketComponent;
}
@Managed(category="Security")
public void setAuthenticationComponent(AuthenticationComponent authenticationComponent)
{
this.authenticationComponent = authenticationComponent;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
* 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
@@ -18,18 +18,19 @@
* 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 recieved a copy of the text describing
* 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.security.authentication;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import net.sf.acegisecurity.Authentication;
import org.alfresco.service.Managed;
import org.alfresco.repo.security.authentication.ntlm.NLTMAuthenticator;
/**
* A chaining authentication component is required for all the beans that qire up an authentication component and not an
@@ -38,7 +39,7 @@ import org.alfresco.service.Managed;
*
* @author andyh
*/
public class ChainingAuthenticationComponentImpl extends AbstractAuthenticationComponent
public class ChainingAuthenticationComponentImpl extends AbstractChainingAuthenticationComponent implements NLTMAuthenticator
{
/**
* NLTM authentication mode - if unset - finds the first component that supports NTLM - if set - finds the first
@@ -72,7 +73,6 @@ public class ChainingAuthenticationComponentImpl extends AbstractAuthenticationC
*
* @param authenticationComponents
*/
@Managed(category = "Security")
public void setAuthenticationComponents(List<AuthenticationComponent> authenticationComponents)
{
this.authenticationComponents = authenticationComponents;
@@ -93,44 +93,20 @@ public class ChainingAuthenticationComponentImpl extends AbstractAuthenticationC
*
* @param mutableAuthenticationComponent
*/
@Managed(category = "Security")
public void setMutableAuthenticationComponent(AuthenticationComponent mutableAuthenticationComponent)
{
this.mutableAuthenticationComponent = mutableAuthenticationComponent;
}
@Managed(category = "Security")
public void setNtlmMode(NTLMMode ntlmMode)
{
this.ntlmMode = ntlmMode;
}
/**
* Chain authentication with user name and password - tries all in order until one works, or fails.
*/
@Override
protected void authenticateImpl(String userName, char[] password)
{
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
try
{
authComponent.authenticate(userName, password);
return;
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Failed to authenticate");
}
/**
* NTLM passthrough authentication - if a mode is defined - the first PASS_THROUGH provider is used - if not, the
* first component that supports NTLM is used if it supports PASS_THROUGH
*/
@Override
public Authentication authenticate(Authentication token) throws AuthenticationException
{
if (this.ntlmMode != null)
@@ -144,9 +120,14 @@ public class ChainingAuthenticationComponentImpl extends AbstractAuthenticationC
case PASS_THROUGH:
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
if (authComponent.getNTLMMode() == NTLMMode.PASS_THROUGH)
if (!(authComponent instanceof NLTMAuthenticator))
{
return authComponent.authenticate(token);
continue;
}
NLTMAuthenticator ssoAuthenticator = (NLTMAuthenticator)authComponent;
if (ssoAuthenticator.getNTLMMode() == NTLMMode.PASS_THROUGH)
{
return ssoAuthenticator.authenticate(token);
}
}
throw new AuthenticationException("No NTLM passthrough authentication to use");
@@ -158,11 +139,16 @@ public class ChainingAuthenticationComponentImpl extends AbstractAuthenticationC
{
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
if (authComponent.getNTLMMode() != NTLMMode.NONE)
if (!(authComponent instanceof NLTMAuthenticator))
{
if (authComponent.getNTLMMode() == NTLMMode.PASS_THROUGH)
continue;
}
NLTMAuthenticator ssoAuthenticator = (NLTMAuthenticator)authComponent;
if (ssoAuthenticator.getNTLMMode() != NTLMMode.NONE)
{
if (ssoAuthenticator.getNTLMMode() == NTLMMode.PASS_THROUGH)
{
return authComponent.authenticate(token);
return ssoAuthenticator.authenticate(token);
}
else
{
@@ -179,7 +165,6 @@ public class ChainingAuthenticationComponentImpl extends AbstractAuthenticationC
/**
* Get the MD4 password hash
*/
@Override
public String getMD4HashedPassword(String userName)
{
if (this.ntlmMode != null)
@@ -193,9 +178,14 @@ public class ChainingAuthenticationComponentImpl extends AbstractAuthenticationC
case MD4_PROVIDER:
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
if (authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
if (!(authComponent instanceof NLTMAuthenticator))
{
return authComponent.getMD4HashedPassword(userName);
continue;
}
NLTMAuthenticator ssoAuthenticator = (NLTMAuthenticator)authComponent;
if (ssoAuthenticator.getNTLMMode() == NTLMMode.MD4_PROVIDER)
{
return ssoAuthenticator.getMD4HashedPassword(userName);
}
}
throw new AuthenticationException("No MD4 provider available");
@@ -207,16 +197,21 @@ public class ChainingAuthenticationComponentImpl extends AbstractAuthenticationC
{
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
if (authComponent.getNTLMMode() != NTLMMode.NONE)
if (!(authComponent instanceof NLTMAuthenticator))
{
if (authComponent.getNTLMMode() == NTLMMode.PASS_THROUGH)
continue;
}
NLTMAuthenticator ssoAuthenticator = (NLTMAuthenticator)authComponent;
if (ssoAuthenticator.getNTLMMode() != NTLMMode.NONE)
{
if (ssoAuthenticator.getNTLMMode() == NTLMMode.PASS_THROUGH)
{
throw new AuthenticationException(
"The first authentication component to support NTLM supports passthrough");
}
else
{
return authComponent.getMD4HashedPassword(userName);
return ssoAuthenticator.getMD4HashedPassword(userName);
}
}
}
@@ -228,7 +223,6 @@ public class ChainingAuthenticationComponentImpl extends AbstractAuthenticationC
/**
* Get the NTLM mode - this is only what is set if one of the implementations provides support for that mode.
*/
@Override
public NTLMMode getNTLMMode()
{
if (this.ntlmMode != null)
@@ -240,7 +234,12 @@ public class ChainingAuthenticationComponentImpl extends AbstractAuthenticationC
case PASS_THROUGH:
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
if (authComponent.getNTLMMode() == NTLMMode.PASS_THROUGH)
if (!(authComponent instanceof NLTMAuthenticator))
{
continue;
}
NLTMAuthenticator ssoAuthenticator = (NLTMAuthenticator)authComponent;
if (ssoAuthenticator.getNTLMMode() == NTLMMode.PASS_THROUGH)
{
return NTLMMode.PASS_THROUGH;
}
@@ -249,7 +248,12 @@ public class ChainingAuthenticationComponentImpl extends AbstractAuthenticationC
case MD4_PROVIDER:
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
if (authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
if (!(authComponent instanceof NLTMAuthenticator))
{
continue;
}
NLTMAuthenticator ssoAuthenticator = (NLTMAuthenticator)authComponent;
if (ssoAuthenticator.getNTLMMode() == NTLMMode.MD4_PROVIDER)
{
return NTLMMode.MD4_PROVIDER;
}
@@ -263,74 +267,26 @@ public class ChainingAuthenticationComponentImpl extends AbstractAuthenticationC
{
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
if (authComponent.getNTLMMode() != NTLMMode.NONE)
if (!(authComponent instanceof NLTMAuthenticator))
{
return authComponent.getNTLMMode();
continue;
}
NLTMAuthenticator ssoAuthenticator = (NLTMAuthenticator)authComponent;
if (ssoAuthenticator.getNTLMMode() != NTLMMode.NONE)
{
return ssoAuthenticator.getNTLMMode();
}
}
return NTLMMode.NONE;
}
}
/**
* If any implementation supports guest then guest is allowed
*/
@Override
protected boolean implementationAllowsGuestLogin()
{
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
if (authComponent.guestUserAuthenticationAllowed())
{
return true;
}
}
return false;
}
@Override
public Authentication setCurrentUser(String userName, UserNameValidationMode validationMode)
{
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
try
{
return authComponent.setCurrentUser(userName, validationMode);
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Failed to set current user " + userName);
}
/**
* Set the current user - try all implementations - as some may check the user exists
*/
@Override
public Authentication setCurrentUser(String userName)
{
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
try
{
return authComponent.setCurrentUser(userName);
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Failed to set current user " + userName);
}
/**
* Helper to get authentication components
*
* @return
*/
private List<AuthenticationComponent> getUsableAuthenticationComponents()
protected Collection<AuthenticationComponent> getUsableAuthenticationComponents()
{
if (this.mutableAuthenticationComponent == null)
{

View File

@@ -25,459 +25,68 @@
package org.alfresco.repo.security.authentication;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.alfresco.service.Managed;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.PermissionService;
/**
* This class implements a simple chaining authentication service.
*
* It chains together other authentication services so that authentication can happen against more than one authentication service.
*
* The authentication services it uses are stored as a list.
*
* Each authentication service must belong to the same domain. This is checked at configuration time.
*
* Authentication will try each authentication service in order. If any allow authentication given the user name and password then the user will be accepted.
*
* Additions, deletions and password changes are made to one special authentication service. This service will be tried first for authentication. Users can not be created if they
* exist in another authentication service.
*
* To avoid transactional issues in chaining, the services registered with this service must not have transactional wrappers. If not, errors will mark the transaction for roll back
* and we can not chain down the list of authentication services.
*
* This class implements a simple chaining authentication service. It chains together other authentication services so
* that authentication can happen against more than one authentication service. The authentication services it uses are
* stored as a list. Each authentication service must belong to the same domain. This is checked at configuration time.
* Authentication will try each authentication service in order. If any allow authentication given the user name and
* password then the user will be accepted. Additions, deletions and password changes are made to one special
* authentication service. This service will be tried first for authentication. Users can not be created if they exist
* in another authentication service. To avoid transactional issues in chaining, the services registered with this
* service must not have transactional wrappers. If not, errors will mark the transaction for roll back and we can not
* chain down the list of authentication services.
*
* @author Andy Hind
*/
public class ChainingAuthenticationServiceImpl extends AbstractAuthenticationService
public class ChainingAuthenticationServiceImpl extends AbstractChainingAuthenticationService
{
private List<AuthenticationService> authenticationServices;
List<AuthenticationService> authenticationServices;
private AuthenticationService mutableAuthenticationService;
AuthenticationService mutableAuthenticationService;
public ChainingAuthenticationServiceImpl()
{
super();
}
public List<AuthenticationService> getAuthenticationServices()
{
return authenticationServices;
}
@Managed(category="Security")
public void setAuthenticationServices(List<AuthenticationService> authenticationServices)
{
this.authenticationServices = authenticationServices;
}
@Override
public AuthenticationService getMutableAuthenticationService()
{
return mutableAuthenticationService;
return this.mutableAuthenticationService;
}
@Managed(category="Security")
public void setMutableAuthenticationService(AuthenticationService mutableAuthenticationService)
{
this.mutableAuthenticationService = mutableAuthenticationService;
}
public void createAuthentication(String userName, char[] password) throws AuthenticationException
@Override
protected List<AuthenticationService> getUsableAuthenticationServices()
{
if (mutableAuthenticationService == null)
if (this.mutableAuthenticationService == null)
{
throw new AuthenticationException(
"Unable to create authentication as there is no suitable authentication service.");
}
mutableAuthenticationService.createAuthentication(userName, password);
}
public void updateAuthentication(String userName, char[] oldPassword, char[] newPassword)
throws AuthenticationException
{
if (mutableAuthenticationService == null)
{
throw new AuthenticationException(
"Unable to update authentication as there is no suitable authentication service.");
}
mutableAuthenticationService.updateAuthentication(userName, oldPassword, newPassword);
}
public void setAuthentication(String userName, char[] newPassword) throws AuthenticationException
{
if (mutableAuthenticationService == null)
{
throw new AuthenticationException(
"Unable to set authentication as there is no suitable authentication service.");
}
mutableAuthenticationService.setAuthentication(userName, newPassword);
}
public void deleteAuthentication(String userName) throws AuthenticationException
{
if (mutableAuthenticationService == null)
{
throw new AuthenticationException(
"Unable to delete authentication as there is no suitable authentication service.");
}
mutableAuthenticationService.deleteAuthentication(userName);
}
public void setAuthenticationEnabled(String userName, boolean enabled) throws AuthenticationException
{
if (mutableAuthenticationService == null)
{
throw new AuthenticationException(
"Unable to set authentication enabled as there is no suitable authentication service.");
}
mutableAuthenticationService.setAuthenticationEnabled(userName, enabled);
}
public boolean getAuthenticationEnabled(String userName) throws AuthenticationException
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
if (authService.getAuthenticationEnabled(userName))
{
return true;
}
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
return false;
}
public void authenticate(String userName, char[] password) throws AuthenticationException
{
preAuthenticationCheck(userName);
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
authService.authenticate(userName, password);
return;
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Failed to authenticate");
}
public void authenticateAsGuest() throws AuthenticationException
{
preAuthenticationCheck(PermissionService.GUEST_AUTHORITY);
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
authService.authenticateAsGuest();
return;
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Guest authentication not supported");
}
public boolean guestUserAuthenticationAllowed()
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
if (authService.guestUserAuthenticationAllowed())
{
return true;
}
}
// it isn't allowed in any of the authentication components
return false;
}
public boolean authenticationExists(String userName)
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
if (authService.authenticationExists(userName))
{
return true;
}
}
// it doesn't exist in any of the authentication components
return false;
}
public String getCurrentUserName() throws AuthenticationException
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
return authService.getCurrentUserName();
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
return null;
}
public void invalidateUserSession(String userName) throws AuthenticationException
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
authService.invalidateUserSession(userName);
return;
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Unable to invalidate user session");
}
public void invalidateTicket(String ticket) throws AuthenticationException
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
authService.invalidateTicket(ticket);
return;
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Unable to invalidate ticket");
}
public void validate(String ticket) throws AuthenticationException
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
authService.validate(ticket);
return;
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Unable to validate ticket");
}
public String getCurrentTicket()
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
return authService.getCurrentTicket();
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
return null;
}
public String getNewTicket()
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
return authService.getNewTicket();
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
return null;
}
public void clearCurrentSecurityContext()
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
authService.clearCurrentSecurityContext();
return;
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Failed to clear security context");
}
public boolean isCurrentUserTheSystemUser()
{
for (AuthenticationService authService : getUsableAuthenticationServices())
{
try
{
return authService.isCurrentUserTheSystemUser();
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
return false;
}
private List<AuthenticationService> getUsableAuthenticationServices()
{
if (mutableAuthenticationService == null)
{
return authenticationServices;
return this.authenticationServices;
}
else
{
ArrayList<AuthenticationService> services = new ArrayList<AuthenticationService>(
authenticationServices == null ? 1 : (authenticationServices.size() + 1));
services.add(mutableAuthenticationService);
if (authenticationServices != null)
this.authenticationServices == null ? 1 : this.authenticationServices.size() + 1);
services.add(this.mutableAuthenticationService);
if (this.authenticationServices != null)
{
services.addAll(authenticationServices);
services.addAll(this.authenticationServices);
}
return services;
}
}
public Set<String> getDomains()
{
HashSet<String> domains = new HashSet<String>();
for (AuthenticationService authService : getUsableAuthenticationServices())
{
domains.addAll(authService.getDomains());
}
return domains;
}
public Set<String> getDomainsThatAllowUserCreation()
{
HashSet<String> domains = new HashSet<String>();
if (mutableAuthenticationService != null)
{
domains.addAll(mutableAuthenticationService.getDomainsThatAllowUserCreation());
}
return domains;
}
public Set<String> getDomainsThatAllowUserDeletion()
{
HashSet<String> domains = new HashSet<String>();
if (mutableAuthenticationService != null)
{
domains.addAll(mutableAuthenticationService.getDomainsThatAllowUserDeletion());
}
return domains;
}
public Set<String> getDomiansThatAllowUserPasswordChanges()
{
HashSet<String> domains = new HashSet<String>();
if (mutableAuthenticationService != null)
{
domains.addAll(mutableAuthenticationService.getDomiansThatAllowUserPasswordChanges());
}
return domains;
}
@Override
public Set<String> getUsersWithTickets(boolean nonExpiredOnly)
{
HashSet<String> users = new HashSet<String>();
for (AuthenticationService authService : getUsableAuthenticationServices())
{
if(authService instanceof AbstractAuthenticationService)
{
users.addAll( ((AbstractAuthenticationService)authService).getUsersWithTickets(nonExpiredOnly));
}
}
return users;
}
@Override
public int countTickets(boolean nonExpiredOnly)
{
int count = 0;
for(TicketComponent tc : getTicketComponents())
{
count += tc.countTickets(nonExpiredOnly);
}
return count;
}
@Override
public int invalidateTickets(boolean nonExpiredOnly)
{
int count = 0;
for (AuthenticationService authService : getUsableAuthenticationServices())
{
if(authService instanceof AbstractAuthenticationService)
{
count += ((AbstractAuthenticationService)authService).invalidateTickets(nonExpiredOnly);
}
}
return count;
}
@Override
public Set<TicketComponent> getTicketComponents()
{
Set<TicketComponent> tcs = new HashSet<TicketComponent>();
for (AuthenticationService authService : getUsableAuthenticationServices())
{
if(authService instanceof AbstractAuthenticationService)
{
tcs.addAll(((AbstractAuthenticationService)authService).getTicketComponents());
}
}
return tcs;
}
public Set<String> getDefaultAdministratorUserNames()
{
Set<String> defaultAdministratorUserNames = new TreeSet<String>();
for (AuthenticationService authService : getUsableAuthenticationServices())
{
defaultAdministratorUserNames.addAll(authService.getDefaultAdministratorUserNames());
}
return defaultAdministratorUserNames;
}
}

View File

@@ -30,7 +30,6 @@ import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.providers.dao.UsernameNotFoundException;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.Managed;
import org.springframework.dao.DataAccessException;
/**
@@ -430,97 +429,81 @@ public class DefaultMutableAuthenticationDao implements MutableAuthenticationDao
// Bean IOC //
// -------- //
@Managed(category="Security")
public void setAllowCreateUser(boolean allowCreateUser)
{
this.allowCreateUser = allowCreateUser;
}
@Managed(category="Security")
public void setAllowDeleteUser(boolean allowDeleteUser)
{
this.allowDeleteUser = allowDeleteUser;
}
@Managed(category="Security")
public void setAllowGetAccountExpiryDate(boolean allowGetAccountExpiryDate)
{
this.allowGetAccountExpiryDate = allowGetAccountExpiryDate;
}
@Managed(category="Security")
public void setAllowGetAccountHasExpired(boolean allowGetAccountHasExpired)
{
this.allowGetAccountHasExpired = allowGetAccountHasExpired;
}
@Managed(category="Security")
public void setAllowGetAccountLocked(boolean allowGetAccountLocked)
{
this.allowGetAccountLocked = allowGetAccountLocked;
}
@Managed(category="Security")
public void setAllowGetCredentialsExpire(boolean allowGetCredentialsExpire)
{
this.allowGetCredentialsExpire = allowGetCredentialsExpire;
}
@Managed(category="Security")
public void setAllowGetCredentialsExpiryDate(boolean allowGetCredentialsExpiryDate)
{
this.allowGetCredentialsExpiryDate = allowGetCredentialsExpiryDate;
}
@Managed(category="Security")
public void setAllowGetCredentialsHaveExpired(boolean allowGetCredentialsHaveExpired)
{
this.allowGetCredentialsHaveExpired = allowGetCredentialsHaveExpired;
}
@Managed(category="Security")
public void setAllowGetEnabled(boolean allowGetEnabled)
{
this.allowGetEnabled = allowGetEnabled;
}
@Managed(category="Security")
public void setAllowSetAccountExpires(boolean allowSetAccountExpires)
{
this.allowSetAccountExpires = allowSetAccountExpires;
}
@Managed(category="Security")
public void setAllowSetAccountExpiryDate(boolean allowSetAccountExpiryDate)
{
this.allowSetAccountExpiryDate = allowSetAccountExpiryDate;
}
@Managed(category="Security")
public void setAllowSetAccountLocked(boolean allowSetAccountLocked)
{
this.allowSetAccountLocked = allowSetAccountLocked;
}
@Managed(category="Security")
public void setAllowSetCredentialsExpire(boolean allowSetCredentialsExpire)
{
this.allowSetCredentialsExpire = allowSetCredentialsExpire;
}
@Managed(category="Security")
public void setAllowSetCredentialsExpiryDate(boolean allowSetCredentialsExpiryDate)
{
this.allowSetCredentialsExpiryDate = allowSetCredentialsExpiryDate;
}
@Managed(category="Security")
public void setAllowSetEnabled(boolean allowSetEnabled)
{
this.allowSetEnabled = allowSetEnabled;
}
@Managed(category="Security")
public void setAllowUpdateUser(boolean allowUpdateUser)
{
this.allowUpdateUser = allowUpdateUser;

View File

@@ -24,6 +24,11 @@
*/
package org.alfresco.repo.security.authentication;
import net.sf.acegisecurity.Authentication;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.security.authentication.ntlm.NLTMAuthenticator;
/**
* This implementation of an AuthenticationComponent can be configured to accept or reject all attempts to login.
@@ -37,7 +42,7 @@ package org.alfresco.repo.security.authentication;
*
* @author Andy Hind
*/
public class SimpleAcceptOrRejectAllAuthenticationComponentImpl extends AbstractAuthenticationComponent
public class SimpleAcceptOrRejectAllAuthenticationComponentImpl extends AbstractAuthenticationComponent implements NLTMAuthenticator
{
private boolean accept = false;
@@ -70,7 +75,6 @@ public class SimpleAcceptOrRejectAllAuthenticationComponentImpl extends Abstract
return accept;
}
@Override
public String getMD4HashedPassword(String userName)
{
if(accept)
@@ -83,11 +87,16 @@ public class SimpleAcceptOrRejectAllAuthenticationComponentImpl extends Abstract
}
}
@Override
public NTLMMode getNTLMMode()
{
return NTLMMode.MD4_PROVIDER;
}
/**
* The default is not to support Authentication token base authentication
*/
public Authentication authenticate(Authentication token) throws AuthenticationException
{
throw new AlfrescoRuntimeException("Authentication via token not supported");
}
}

View File

@@ -40,7 +40,6 @@ import javax.security.sasl.RealmCallback;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.security.authentication.AbstractAuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.service.Managed;
/**
* JAAS based authentication
@@ -104,14 +103,12 @@ public class JAASAuthenticationComponent extends AbstractAuthenticationComponent
// Springification
@Managed(category="Security")
public void setJaasConfigEntryName(String jaasConfigEntryName)
{
this.jaasConfigEntryName = jaasConfigEntryName;
}
@Managed(category="Security")
public void setRealm(String realm)
{
this.realm = realm;

View File

@@ -29,7 +29,6 @@ import javax.naming.directory.InitialDirContext;
import org.alfresco.repo.security.authentication.AbstractAuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.service.Managed;
/**
* Currently expects the cn name of the user which is in a fixed location.
@@ -51,25 +50,21 @@ public class LDAPAuthenticationComponentImpl extends AbstractAuthenticationCompo
super();
}
@Managed(category="Security")
public void setLDAPInitialDirContextFactory(LDAPInitialDirContextFactory ldapInitialDirContextFactory)
{
this.ldapInitialContextFactory = ldapInitialDirContextFactory;
}
@Managed(category="Security")
public void setUserNameFormat(String userNameFormat)
{
this.userNameFormat = userNameFormat;
}
@Managed(category="Security")
public void setEscapeCommasInBind(boolean escapeCommasInBind)
{
this.escapeCommasInBind = escapeCommasInBind;
}
@Managed(category="Security")
public void setEscapeCommasInUid(boolean escapeCommasInUid)
{
this.escapeCommasInUid = escapeCommasInUid;

View File

@@ -38,7 +38,6 @@ import javax.naming.directory.BasicAttributes;
import javax.naming.directory.InitialDirContext;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.service.Managed;
import org.alfresco.util.ApplicationContextHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -61,7 +60,6 @@ public class LDAPInitialDirContextFactoryImpl implements LDAPInitialDirContextFa
super();
}
@Managed(category="Security")
public void setInitialDirContextEnvironment(Map<String, String> initialDirContextEnvironment)
{
this.initialDirContextEnvironment = initialDirContextEnvironment;

View File

@@ -44,7 +44,6 @@ import javax.transaction.UserTransaction;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.importer.ExportSource;
import org.alfresco.repo.importer.ExportSourceImporterException;
import org.alfresco.service.Managed;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
@@ -85,25 +84,21 @@ public class LDAPPersonExportSource implements ExportSource
super();
}
@Managed(category="Security")
public void setPersonQuery(String personQuery)
{
this.personQuery = personQuery;
}
@Managed(category="Security")
public void setSearchBase(String searchBase)
{
this.searchBase = searchBase;
}
@Managed(category="Security")
public void setUserIdAttributeName(String userIdAttributeName)
{
this.userIdAttributeName = userIdAttributeName;
}
@Managed(category="Security")
public void setLDAPInitialDirContextFactory(LDAPInitialDirContextFactory ldapInitialDirContextFactory)
{
this.ldapInitialContextFactory = ldapInitialDirContextFactory;
@@ -114,7 +109,6 @@ public class LDAPPersonExportSource implements ExportSource
this.personService = personService;
}
@Managed(category="Security")
public void setAttributeDefaults(Map<String, String> attributeDefaults)
{
this.attributeDefaults = attributeDefaults;
@@ -125,13 +119,11 @@ public class LDAPPersonExportSource implements ExportSource
this.namespaceService = namespaceService;
}
@Managed(category="Security")
public void setAttributeMapping(Map<String, String> attributeMapping)
{
this.attributeMapping = attributeMapping;
}
@Managed(category="Security")
public void setErrorOnMissingUID(boolean errorOnMissingUID)
{
this.errorOnMissingUID = errorOnMissingUID;
@@ -175,7 +167,7 @@ public class LDAPPersonExportSource implements ExportSource
userSearchCtls.setCountLimit(Integer.MAX_VALUE);
NamingEnumeration searchResults = ctx.search(searchBase, personQuery, userSearchCtls);
NamingEnumeration<SearchResult> searchResults = ctx.search(searchBase, personQuery, userSearchCtls);
RESULT_LOOP: while (searchResults.hasMoreElements())
{
SearchResult result = (SearchResult) searchResults.next();

View File

@@ -0,0 +1,68 @@
/*
* 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.security.authentication.ntlm;
import net.sf.acegisecurity.Authentication;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.NTLMMode;
/**
* An specialized {@link AuthenticationComponent} that is capable of handling NTLM authentication directly, either by
* 'passing through' to a domain server or by validating an MD4 hashed password. Unlike other authentication methods,
* these operations cannot be chained and must be handled by a specific authentication component.
*
* @author dward
*/
public interface NLTMAuthenticator extends AuthenticationComponent
{
/**
* Authenticate using a token.
*
* @param token
* Authentication
* @return Authentication
* @throws AuthenticationException
* the authentication exception
*/
public Authentication authenticate(Authentication token) throws AuthenticationException;
/**
* Get the enum that describes NTLM integration.
*
* @return the NTLM mode
*/
public NTLMMode getNTLMMode();
/**
* Get the MD4 password hash, as required by NTLM based authentication methods.
*
* @param userName
* the user name
* @return the m d4 hashed password
*/
public String getMD4HashedPassword(String userName);
}

View File

@@ -67,7 +67,7 @@ import org.springframework.beans.factory.InitializingBean;
*
* @author GKSpencer
*/
public class NTLMAuthenticationComponentImpl extends AbstractAuthenticationComponent implements InitializingBean
public class NTLMAuthenticationComponentImpl extends AbstractAuthenticationComponent implements NLTMAuthenticator, InitializingBean
{
// Logging

View File

@@ -0,0 +1,92 @@
/*
* 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.security.authentication.subsystems;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.alfresco.repo.management.subsystems.ChildApplicationContextManager;
import org.alfresco.repo.security.authentication.AbstractChainingAuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
/**
* An authentication component that chains across beans in multiple child application contexts corresponding to
* different 'subsystems' in a chain determined by a {@link ChildApplicationContextManager}.
*
* @author dward
*/
public class SubsystemChainingAuthenticationComponent extends AbstractChainingAuthenticationComponent
{
private ChildApplicationContextManager applicationContextManager;
private String sourceBeanName;
/**
* @param applicationContextManager
* the applicationContextManager to set
*/
public void setApplicationContextManager(ChildApplicationContextManager applicationContextManager)
{
this.applicationContextManager = applicationContextManager;
}
/**
* Sets the name of the bean to look up in the child application contexts.
*
* @param sourceBeanName
* the bean name
*/
public void setSourceBeanName(String sourceBeanName)
{
this.sourceBeanName = sourceBeanName;
}
/*
* (non-Javadoc)
* @see
* org.alfresco.repo.security.authentication.AbstractChainingAuthenticationCompent#getUsableAuthenticationComponents
* ()
*/
@Override
protected Collection<AuthenticationComponent> getUsableAuthenticationComponents()
{
List<AuthenticationComponent> result = new LinkedList<AuthenticationComponent>();
for (String instance : this.applicationContextManager.getInstanceIds())
{
ApplicationContext context = this.applicationContextManager.getApplicationContext(instance);
try
{
result.add((AuthenticationComponent) context.getBean(sourceBeanName));
}
catch (NoSuchBeanDefinitionException e)
{
// Ignore and continue
}
}
return result;
}
}

View File

@@ -0,0 +1,120 @@
/*
* 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.security.authentication.subsystems;
import java.util.LinkedList;
import java.util.List;
import org.alfresco.repo.management.subsystems.ChildApplicationContextManager;
import org.alfresco.repo.security.authentication.AbstractChainingAuthenticationService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
/**
* An authentication service that chains across beans in multiple child application contexts corresponding to different
* 'subsystems' in a chain determined by a {@link ChildApplicationContextManager}. The first authentication service in
* the chain will always be considered to be the 'mutable' authentication service.
*
* @author dward
*/
public class SubsystemChainingAuthenticationService extends AbstractChainingAuthenticationService
{
/** The application context manager. */
private ChildApplicationContextManager applicationContextManager;
/** The source bean name. */
private String sourceBeanName;
/**
* Sets the application context manager.
*
* @param applicationContextManager
* the applicationContextManager to set
*/
public void setApplicationContextManager(ChildApplicationContextManager applicationContextManager)
{
this.applicationContextManager = applicationContextManager;
}
/**
* Sets the name of the bean to look up in the child application contexts.
*
* @param sourceBeanName
* the bean name
*/
public void setSourceBeanName(String sourceBeanName)
{
this.sourceBeanName = sourceBeanName;
}
/*
* (non-Javadoc)
* @see
* org.alfresco.repo.security.authentication.AbstractChainingAuthenticationService#getMutableAuthenticationService()
*/
@Override
public AuthenticationService getMutableAuthenticationService()
{
for (String instance : this.applicationContextManager.getInstanceIds())
{
ApplicationContext context = this.applicationContextManager.getApplicationContext(instance);
try
{
return (AuthenticationService) context.getBean(sourceBeanName);
}
catch (NoSuchBeanDefinitionException e)
{
// Ignore and continue
}
}
return null;
}
/*
* (non-Javadoc)
* @see
* org.alfresco.repo.security.authentication.AbstractChainingAuthenticationService#getUsableAuthenticationServices()
*/
@Override
protected List<AuthenticationService> getUsableAuthenticationServices()
{
List<AuthenticationService> result = new LinkedList<AuthenticationService>();
for (String instance : this.applicationContextManager.getInstanceIds())
{
ApplicationContext context = this.applicationContextManager.getApplicationContext(instance);
try
{
result.add((AuthenticationService) context.getBean(sourceBeanName));
}
catch (NoSuchBeanDefinitionException e)
{
// Ignore and continue
}
}
return result;
}
}