MOB-412: Decouple thread local authentication methods from AuthenticationComponent into new AuthenticationContext super-interface. The AuthenticationContext is a delegate of AbstractAuthenticationComponent and can be accessed directly by low-level classes (e.g. schema bootstrap) before the authentication subsystem is available.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13721 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Dave Ward
2009-03-23 14:01:29 +00:00
parent 61442fd07b
commit facbdaf5b7
43 changed files with 16171 additions and 16073 deletions

View File

@@ -1,125 +1,123 @@
/*
* Copyright (C) 2005-2007 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 recieved 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.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import net.sf.acegisecurity.providers.dao.User;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.transaction.TransactionService;
/**
* This class abstract the support required to set up and query the Acegi context for security enforcement. There are
* some simple default method implementations to support simple authentication.
*
* @author Andy Hind
*/
public abstract class AbstractAuthenticationComponent implements AuthenticationComponent
{
/**
* The abstract class keeps track of support for guest login
*/
private Boolean allowGuestLogin = null;
private TenantService tenantService;
private PersonService personService;
private NodeService nodeService;
private TransactionService transactionService;
private Set<String> defaultAdministratorUserNames = Collections.emptySet();
private boolean autoCreatePeopleOnLogin = true;
public AbstractAuthenticationComponent()
{
super();
}
/**
* Set if guest login is supported.
*
* @param allowGuestLogin
*/
public void setAllowGuestLogin(Boolean allowGuestLogin)
{
this.allowGuestLogin = allowGuestLogin;
}
public void setTenantService(TenantService tenantService)
{
this.tenantService = tenantService;
}
public void setPersonService(PersonService personService)
{
this.personService = personService;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
}
public TransactionService getTransactionService()
{
return transactionService;
}
public Boolean getAllowGuestLogin()
{
return allowGuestLogin;
}
/*
* Copyright (C) 2005-2007 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 recieved 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.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.providers.dao.User;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.transaction.TransactionService;
/**
* This class abstract the support required to set up and query the Acegi context for security enforcement. There are
* some simple default method implementations to support simple authentication.
*
* @author Andy Hind
*/
public abstract class AbstractAuthenticationComponent implements AuthenticationComponent
{
/**
* The abstract class keeps track of support for guest login
*/
private Boolean allowGuestLogin = null;
private Set<String> defaultAdministratorUserNames = Collections.emptySet();
private boolean autoCreatePeopleOnLogin = true;
private AuthenticationContext authenticationContext;
private PersonService personService;
private NodeService nodeService;
private TransactionService transactionService;
public AbstractAuthenticationComponent()
{
super();
}
/**
* Set if guest login is supported.
*
* @param allowGuestLogin
*/
public void setAllowGuestLogin(Boolean allowGuestLogin)
{
this.allowGuestLogin = allowGuestLogin;
}
public void setAuthenticationContext(AuthenticationContext authenticationContext)
{
this.authenticationContext = authenticationContext;
}
public void setPersonService(PersonService personService)
{
this.personService = personService;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
}
public TransactionService getTransactionService()
{
return transactionService;
}
public Boolean getAllowGuestLogin()
{
return allowGuestLogin;
}
public NodeService getNodeService()
{
return nodeService;
@@ -130,56 +128,56 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
return personService;
}
public boolean isAutoCreatePeopleOnLogin()
{
return autoCreatePeopleOnLogin;
}
public void setAutoCreatePeopleOnLogin(boolean autoCreatePeopleOnLogin)
{
this.autoCreatePeopleOnLogin = autoCreatePeopleOnLogin;
}
public void authenticate(String userName, char[] password) throws AuthenticationException
{
// Support guest login from the login screen
if (isGuestUserName(userName))
{
setGuestUserAsCurrentUser(tenantService.getUserDomain(userName));
}
else
{
authenticateImpl(userName, password);
}
}
/**
* Default unsupported authentication implementation - as of 2.1 this is the best way to implement your own
* authentication component as it will support guest login - prior to this direct over ride for authenticate(String ,
* char[]) was used. This will still work.
*
* @param userName
* @param password
*/
protected void authenticateImpl(String userName, char[] password)
{
throw new UnsupportedOperationException();
}
public Authentication setCurrentUser(String userName, UserNameValidationMode validationMode)
{
switch (validationMode)
{
case NONE:
public boolean isAutoCreatePeopleOnLogin()
{
return autoCreatePeopleOnLogin;
}
public void setAutoCreatePeopleOnLogin(boolean autoCreatePeopleOnLogin)
{
this.autoCreatePeopleOnLogin = autoCreatePeopleOnLogin;
}
public void authenticate(String userName, char[] password) throws AuthenticationException
{
// Support guest login from the login screen
if (isGuestUserName(userName))
{
setGuestUserAsCurrentUser(getUserDomain(userName));
}
else
{
authenticateImpl(userName, password);
}
}
/**
* Default unsupported authentication implementation - as of 2.1 this is the best way to implement your own
* authentication component as it will support guest login - prior to this direct over ride for authenticate(String ,
* char[]) was used. This will still work.
*
* @param userName
* @param password
*/
protected void authenticateImpl(String userName, char[] password)
{
throw new UnsupportedOperationException();
}
public Authentication setCurrentUser(String userName, UserNameValidationMode validationMode)
{
switch (validationMode)
{
case NONE:
return setCurrentUserImpl(userName);
case CHECK_AND_FIX:
default:
return setCurrentUser(userName);
}
}
public Authentication setCurrentUser(final String userName) throws AuthenticationException
{
case CHECK_AND_FIX:
default:
return setCurrentUser(userName);
}
}
public Authentication setCurrentUser(final String userName) throws AuthenticationException
{
if (isSystemUserName(userName))
{
return setCurrentUserImpl(userName);
@@ -223,39 +221,29 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
throw new AuthenticationException("Null user name");
}
if (isSystemUserName(userName))
{
return setSystemUserAsCurrentUser(getUserDomain(userName));
}
try
{
UserDetails ud = null;
if (isSystemUserName(userName))
{
GrantedAuthority[] gas = new GrantedAuthority[1];
gas[0] = new GrantedAuthorityImpl("ROLE_SYSTEM");
ud = new User(userName, "", true, true, true, true, gas);
}
else if (isGuestUserName(userName))
if (isGuestUserName(userName))
{
GrantedAuthority[] gas = new GrantedAuthority[0];
ud = new User(getGuestUserName(tenantService.getUserDomain(userName)), "", true, true, true, true, gas);
ud = new User(getGuestUserName(getUserDomain(userName)), "", true, true, true, true, gas);
}
else
{
ud = getUserDetails(userName);
}
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(ud, "", ud.getAuthorities());
auth.setDetails(ud);
auth.setAuthenticated(true);
return setCurrentAuthentication(auth);
return setUserDetails(ud);
}
catch (net.sf.acegisecurity.AuthenticationException ae)
{
throw new AuthenticationException(ae.getMessage(), ae);
}
finally
{
// Support for logging tenantdomain / username (via log4j NDC)
AuthenticationUtil.logNDC(userName);
}
}
/**
@@ -270,175 +258,177 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
gas[0] = new GrantedAuthorityImpl("ROLE_AUTHENTICATED");
UserDetails ud = new User(userName, "", true, true, true, true, gas);
return ud;
}
/**
* {@inheritDoc}
*/
public Authentication setCurrentAuthentication(Authentication authentication)
{
return AuthenticationUtil.setFullAuthentication(authentication);
}
/**
* Get the current authentication context
*
* @return Authentication
* @throws AuthenticationException
*/
public Authentication getCurrentAuthentication() throws AuthenticationException
{
return AuthenticationUtil.getFullAuthentication();
}
/**
* Get the current user name.
*
* @return String
* @throws AuthenticationException
*/
public String getCurrentUserName() throws AuthenticationException
{
return AuthenticationUtil.getFullyAuthenticatedUser();
}
/**
* Set the system user as the current user note: for MT, will set to default domain only
*
* @return Authentication
*/
public Authentication setSystemUserAsCurrentUser()
{
return setCurrentUser(AuthenticationUtil.SYSTEM_USER_NAME);
}
/**
* Get the name of the system user note: for MT, will get system for default domain only
*
* @return String
*/
public String getSystemUserName()
{
return AuthenticationUtil.SYSTEM_USER_NAME;
}
/**
* Is this the system user ?
*
* @return boolean
*/
public boolean isSystemUserName(String userName)
{
return (getSystemUserName().equals(tenantService.getBaseNameUser(userName)));
}
/**
* Get the name of the Guest User note: for MT, will get guest for default domain only
*
* @return String
*/
public String getGuestUserName()
{
return PermissionService.GUEST_AUTHORITY.toLowerCase();
}
private String getGuestUserName(String tenantDomain)
{
return tenantService.getDomainUser(getGuestUserName(), tenantDomain);
}
/**
* Set the guest user as the current user. note: for MT, will set to default domain only
*/
public Authentication setGuestUserAsCurrentUser() throws AuthenticationException
{
return setGuestUserAsCurrentUser(TenantService.DEFAULT_DOMAIN);
}
/**
* Set the guest user as the current user.
*/
private Authentication setGuestUserAsCurrentUser(String tenantDomain) throws AuthenticationException
{
if (allowGuestLogin == null)
{
if (implementationAllowsGuestLogin())
{
return setCurrentUser(getGuestUserName(tenantDomain));
}
else
{
throw new AuthenticationException("Guest authentication is not allowed");
}
}
else
{
if (allowGuestLogin.booleanValue())
{
return setCurrentUser(getGuestUserName(tenantDomain));
}
else
{
throw new AuthenticationException("Guest authentication is not allowed");
}
}
}
private boolean isGuestUserName(String userName)
{
return (PermissionService.GUEST_AUTHORITY.equalsIgnoreCase(tenantService.getBaseNameUser(userName)));
}
protected abstract boolean implementationAllowsGuestLogin();
/**
* @return true if Guest user authentication is allowed, false otherwise
*/
public boolean guestUserAuthenticationAllowed()
{
if (allowGuestLogin == null)
{
return (implementationAllowsGuestLogin());
}
else
{
return (allowGuestLogin.booleanValue());
}
}
/**
* Remove the current security information
*/
public void clearCurrentSecurityContext()
{
AuthenticationUtil.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;
}
}
/**
* {@inheritDoc}
*/
public Authentication setCurrentAuthentication(Authentication authentication)
{
return this.authenticationContext.setCurrentAuthentication(authentication);
}
/**
* Get the current authentication context
*
* @return Authentication
* @throws AuthenticationException
*/
public Authentication getCurrentAuthentication() throws AuthenticationException
{
return authenticationContext.getCurrentAuthentication();
}
/**
* Get the current user name.
*
* @return String
* @throws AuthenticationException
*/
public String getCurrentUserName() throws AuthenticationException
{
return authenticationContext.getCurrentUserName();
}
/**
* Set the system user as the current user note: for MT, will set to default domain only
*
* @return Authentication
*/
public Authentication setSystemUserAsCurrentUser()
{
return authenticationContext.setSystemUserAsCurrentUser();
}
/**
* Get the name of the system user note: for MT, will get system for default domain only
*
* @return String
*/
public String getSystemUserName()
{
return authenticationContext.getSystemUserName();
}
/**
* Is this the system user ?
*
* @return boolean
*/
public boolean isSystemUserName(String userName)
{
return authenticationContext.isSystemUserName(userName);
}
/**
* Get the name of the Guest User note: for MT, will get guest for default domain only
*
* @return String
*/
public String getGuestUserName()
{
return authenticationContext.getGuestUserName();
}
public String getGuestUserName(String tenantDomain)
{
return authenticationContext.getGuestUserName(tenantDomain);
}
/**
* Set the guest user as the current user. note: for MT, will set to default domain only
*/
public Authentication setGuestUserAsCurrentUser() throws AuthenticationException
{
return setGuestUserAsCurrentUser(TenantService.DEFAULT_DOMAIN);
}
/**
* Set the guest user as the current user.
*/
private Authentication setGuestUserAsCurrentUser(String tenantDomain) throws AuthenticationException
{
if (allowGuestLogin == null)
{
if (implementationAllowsGuestLogin())
{
return setCurrentUser(getGuestUserName(tenantDomain));
}
else
{
throw new AuthenticationException("Guest authentication is not allowed");
}
}
else
{
if (allowGuestLogin.booleanValue())
{
return setCurrentUser(getGuestUserName(tenantDomain));
}
else
{
throw new AuthenticationException("Guest authentication is not allowed");
}
}
}
public boolean isGuestUserName(String userName)
{
return authenticationContext.isGuestUserName(userName);
}
protected abstract boolean implementationAllowsGuestLogin();
/**
* @return true if Guest user authentication is allowed, false otherwise
*/
public boolean guestUserAuthenticationAllowed()
{
if (allowGuestLogin == null)
{
return (implementationAllowsGuestLogin());
}
else
{
return (allowGuestLogin.booleanValue());
}
}
/**
* Remove the current security information
*/
public void clearCurrentSecurityContext()
{
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;
@@ -490,7 +480,7 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
return userName;
}
}
}, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantService.getUserDomain(userName)));
}, getSystemUserName(getUserDomain(userName)));
return setCurrentUserImpl(name);
}
@@ -502,38 +492,58 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
}
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.security.authentication.AuthenticationComponent#getDefaultAdministratorUserNames()
*/
public Set<String> getDefaultAdministratorUserNames()
{
return this.defaultAdministratorUserNames;
}
/**
* Sets the user names who for this particular authentication system should be considered administrators by default.
*
* @param defaultAdministratorUserNames
* a set of user names
*/
public void setDefaultAdministratorUserNames(Set<String> defaultAdministratorUserNames)
{
this.defaultAdministratorUserNames = defaultAdministratorUserNames;
}
/**
* Convenience method to allow the administrator user names to be specified as a comma separated list
*
* @param defaultAdministratorUserNames
*/
public void setDefaultAdministratorUserNames(String defaultAdministratorUserNames)
{
Set<String> nameSet = new TreeSet<String>();
if (defaultAdministratorUserNames.length() > 0)
{
nameSet.addAll(Arrays.asList(defaultAdministratorUserNames.split(",")));
}
setDefaultAdministratorUserNames(nameSet);
}
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.security.authentication.AuthenticationComponent#getDefaultAdministratorUserNames()
*/
public Set<String> getDefaultAdministratorUserNames()
{
return this.defaultAdministratorUserNames;
}
/**
* Sets the user names who for this particular authentication system should be considered administrators by default.
*
* @param defaultAdministratorUserNames
* a set of user names
*/
public void setDefaultAdministratorUserNames(Set<String> defaultAdministratorUserNames)
{
this.defaultAdministratorUserNames = defaultAdministratorUserNames;
}
/**
* Convenience method to allow the administrator user names to be specified as a comma separated list
*
* @param defaultAdministratorUserNames
*/
public void setDefaultAdministratorUserNames(String defaultAdministratorUserNames)
{
Set<String> nameSet = new TreeSet<String>();
if (defaultAdministratorUserNames.length() > 0)
{
nameSet.addAll(Arrays.asList(defaultAdministratorUserNames.split(",")));
}
setDefaultAdministratorUserNames(nameSet);
}
public String getSystemUserName(String tenantDomain)
{
return authenticationContext.getSystemUserName(tenantDomain);
}
public String getUserDomain(String userName)
{
return authenticationContext.getUserDomain(userName);
}
public Authentication setSystemUserAsCurrentUser(String tenantDomain)
{
return authenticationContext.setSystemUserAsCurrentUser(tenantDomain);
}
public Authentication setUserDetails(UserDetails ud)
{
return authenticationContext.setUserDetails(ud);
}
}

View File

@@ -28,9 +28,8 @@ import java.util.Set;
import net.sf.acegisecurity.Authentication;
public interface AuthenticationComponent
public interface AuthenticationComponent extends AuthenticationContext
{
public enum UserNameValidationMode
{
NONE, CHECK_AND_FIX;
@@ -65,33 +64,6 @@ public interface AuthenticationComponent
public Authentication setCurrentUser(String userName, UserNameValidationMode validationMode);
/**
* Remove the current security information
*
*/
public void clearCurrentSecurityContext();
/**
* Explicitly set the current suthentication. If the authentication is <tt>null</tt> the
* the current authentication is {@link #clearCurrentSecurityContext() cleared}.
*
* @param authentication the current authentication (may be <tt>null</tt>).
*
* @return Returns the modified authentication instance or <tt>null</tt> if it was cleared.
*/
public Authentication setCurrentAuthentication(Authentication authentication);
/**
*
* @throws AuthenticationException
*/
public Authentication getCurrentAuthentication() throws AuthenticationException;
/**
* Set the system user as the current user.
*/
public Authentication setSystemUserAsCurrentUser();
/**
* Set the guest user as the current user.
@@ -104,29 +76,6 @@ public interface AuthenticationComponent
*/
public boolean guestUserAuthenticationAllowed();
/**
* Get the name of the system user
*/
public String getSystemUserName();
/**
* True if this is the System user ?
*/
public boolean isSystemUserName(String userName);
/**
* Get the name of the guest user
*/
public String getGuestUserName();
/**
* Get the current user name.
*
* @throws AuthenticationException
*/
public String getCurrentUserName() throws AuthenticationException;
/**
* Get the enum that describes NTLM integration
*/

View File

@@ -0,0 +1,122 @@
/*
* Copyright (C) 2005-2007 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 recieved 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 net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.UserDetails;
/**
* Low-level interface allowing control and retrieval of the authentication information held for the current thread.
*
* @author dward
*/
public interface AuthenticationContext
{
/**
* Remove the current security information
*/
public void clearCurrentSecurityContext();
/**
* Explicitly set the current suthentication. If the authentication is <tt>null</tt> the the current authentication
* is {@link #clearCurrentSecurityContext() cleared}.
*
* @param authentication
* the current authentication (may be <tt>null</tt>).
* @return Returns the modified authentication instance or <tt>null</tt> if it was cleared.
*/
public Authentication setCurrentAuthentication(Authentication authentication);
/**
* Explicitly set the given validated user details to be authenticated.
*
* @param ud
* the User Details
* @return Authentication
*/
public Authentication setUserDetails(UserDetails ud);
/**
* @throws AuthenticationException
*/
public Authentication getCurrentAuthentication() throws AuthenticationException;
/**
* Set the system user as the current user.
*/
public Authentication setSystemUserAsCurrentUser();
/**
* Set the system user as the current user.
*/
public Authentication setSystemUserAsCurrentUser(String tenantDomain);
/**
* Get the name of the system user. Note: for MT, will get system for default domain only
*/
public String getSystemUserName();
/**
* Get the name of the system user
*/
public String getSystemUserName(String tenantDomain);
/**
* True if this is the System user ?
*/
public boolean isSystemUserName(String userName);
/**
* Get the name of the Guest User. Note: for MT, will get guest for default domain only
*/
public String getGuestUserName();
/**
* Get the name of the guest user
*/
public String getGuestUserName(String tenantDomain);
/**
* True if this is a guest user ?
*/
public boolean isGuestUserName(String userName);
/**
* Get the current user name.
*
* @throws AuthenticationException
*/
public String getCurrentUserName() throws AuthenticationException;
/**
* Extracts the tenant domain name from a user name
*
* @param userName
* a user name
* @return a tenant domain name
*/
public String getUserDomain(String userName);
}

View File

@@ -0,0 +1,144 @@
/*
* 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 net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import net.sf.acegisecurity.providers.dao.User;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.security.PermissionService;
/**
* @author Andy Hind
* @author dward
*/
public class AuthenticationContextImpl implements AuthenticationContext
{
private TenantService tenantService;
public void setTenantService(TenantService tenantService)
{
this.tenantService = tenantService;
}
/**
* Explicitly set the given validated user details to be authenticated.
*
* @param ud
* the User Details
* @return Authentication
*/
public Authentication setUserDetails(UserDetails ud)
{
try
{
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(ud, "", ud
.getAuthorities());
auth.setDetails(ud);
auth.setAuthenticated(true);
return setCurrentAuthentication(auth);
}
catch (net.sf.acegisecurity.AuthenticationException ae)
{
throw new AuthenticationException(ae.getMessage(), ae);
}
finally
{
// Support for logging tenantdomain / username (via log4j NDC)
AuthenticationUtil.logNDC(ud.getUsername());
}
}
public Authentication setSystemUserAsCurrentUser()
{
return setSystemUserAsCurrentUser(TenantService.DEFAULT_DOMAIN);
}
public Authentication setSystemUserAsCurrentUser(String tenantDomain)
{
GrantedAuthority[] gas = new GrantedAuthority[1];
gas[0] = new GrantedAuthorityImpl("ROLE_SYSTEM");
return setUserDetails(new User(getSystemUserName(tenantDomain), "", true, true, true, true, gas));
}
public String getSystemUserName()
{
return AuthenticationUtil.SYSTEM_USER_NAME;
}
public String getSystemUserName(String tenantDomain)
{
return this.tenantService.getDomainUser(getSystemUserName(), tenantDomain);
}
public boolean isSystemUserName(String userName)
{
return getSystemUserName().equals(this.tenantService.getBaseNameUser(userName));
}
public String getGuestUserName(String tenantDomain)
{
return this.tenantService.getDomainUser(getGuestUserName(), tenantDomain);
}
public String getGuestUserName()
{
return PermissionService.GUEST_AUTHORITY.toLowerCase();
}
public boolean isGuestUserName(String userName)
{
return PermissionService.GUEST_AUTHORITY.equalsIgnoreCase(this.tenantService.getBaseNameUser(userName));
}
public Authentication setCurrentAuthentication(Authentication authentication)
{
return AuthenticationUtil.setFullAuthentication(authentication);
}
public Authentication getCurrentAuthentication() throws AuthenticationException
{
return AuthenticationUtil.getFullAuthentication();
}
public String getCurrentUserName() throws AuthenticationException
{
return AuthenticationUtil.getFullyAuthenticatedUser();
}
public void clearCurrentSecurityContext()
{
AuthenticationUtil.clearCurrentSecurityContext();
}
public String getUserDomain(String userName)
{
return this.tenantService.getUserDomain(userName);
}
}

View File

@@ -26,13 +26,10 @@ package org.alfresco.repo.security.authentication;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import net.sf.acegisecurity.Authentication;
import org.alfresco.service.Managed;
import org.alfresco.service.cmr.security.PermissionService;
/**
* A chaining authentication component is required for all the beans that qire up an authentication component and not an
@@ -41,7 +38,7 @@ import org.alfresco.service.cmr.security.PermissionService;
*
* @author andyh
*/
public class ChainingAuthenticationComponentImpl implements AuthenticationComponent
public class ChainingAuthenticationComponentImpl extends AbstractAuthenticationComponent
{
/**
* NLTM authentication mode - if unset - finds the first component that supports NTLM - if set - finds the first
@@ -67,7 +64,7 @@ public class ChainingAuthenticationComponentImpl implements AuthenticationCompon
*/
public List<AuthenticationComponent> getAuthenticationComponents()
{
return authenticationComponents;
return this.authenticationComponents;
}
/**
@@ -75,7 +72,7 @@ public class ChainingAuthenticationComponentImpl implements AuthenticationCompon
*
* @param authenticationComponents
*/
@Managed(category="Security")
@Managed(category = "Security")
public void setAuthenticationComponents(List<AuthenticationComponent> authenticationComponents)
{
this.authenticationComponents = authenticationComponents;
@@ -88,7 +85,7 @@ public class ChainingAuthenticationComponentImpl implements AuthenticationCompon
*/
public AuthenticationComponent getMutableAuthenticationComponent()
{
return mutableAuthenticationComponent;
return this.mutableAuthenticationComponent;
}
/**
@@ -96,15 +93,13 @@ public class ChainingAuthenticationComponentImpl implements AuthenticationCompon
*
* @param mutableAuthenticationComponent
*/
@Managed(category="Security")
@Managed(category = "Security")
public void setMutableAuthenticationComponent(AuthenticationComponent mutableAuthenticationComponent)
{
this.mutableAuthenticationComponent = mutableAuthenticationComponent;
}
@Managed(category="Security")
@Managed(category = "Security")
public void setNtlmMode(NTLMMode ntlmMode)
{
this.ntlmMode = ntlmMode;
@@ -113,7 +108,8 @@ public class ChainingAuthenticationComponentImpl implements AuthenticationCompon
/**
* Chain authentication with user name and password - tries all in order until one works, or fails.
*/
public void authenticate(String userName, char[] password) throws AuthenticationException
@Override
protected void authenticateImpl(String userName, char[] password)
{
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
@@ -134,11 +130,12 @@ public class ChainingAuthenticationComponentImpl implements AuthenticationCompon
* 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 (ntlmMode != null)
if (this.ntlmMode != null)
{
switch (ntlmMode)
switch (this.ntlmMode)
{
case NONE:
throw new AuthenticationException("NTLM is not supported");
@@ -169,7 +166,8 @@ public class ChainingAuthenticationComponentImpl implements AuthenticationCompon
}
else
{
throw new AuthenticationException("The first authentication component to support NTLM supports MD4 hashing");
throw new AuthenticationException(
"The first authentication component to support NTLM supports MD4 hashing");
}
}
}
@@ -178,46 +176,15 @@ public class ChainingAuthenticationComponentImpl implements AuthenticationCompon
}
/**
* Clear the security context
*/
public void clearCurrentSecurityContext()
{
AuthenticationUtil.clearCurrentSecurityContext();
}
/**
* Get the current authentication
*/
public Authentication getCurrentAuthentication() throws AuthenticationException
{
return AuthenticationUtil.getFullAuthentication();
}
/**
* Get the current user name
*/
public String getCurrentUserName() throws AuthenticationException
{
return AuthenticationUtil.getFullyAuthenticatedUser();
}
/**
* Get the guest user name
*/
public String getGuestUserName()
{
return PermissionService.GUEST_AUTHORITY.toLowerCase();
}
/**
* Get the MD4 password hash
*/
@Override
public String getMD4HashedPassword(String userName)
{
if (ntlmMode != null)
if (this.ntlmMode != null)
{
switch (ntlmMode)
switch (this.ntlmMode)
{
case NONE:
throw new AuthenticationException("NTLM is not supported");
@@ -244,7 +211,8 @@ public class ChainingAuthenticationComponentImpl implements AuthenticationCompon
{
if (authComponent.getNTLMMode() == NTLMMode.PASS_THROUGH)
{
throw new AuthenticationException("The first authentication component to support NTLM supports passthrough");
throw new AuthenticationException(
"The first authentication component to support NTLM supports passthrough");
}
else
{
@@ -260,11 +228,12 @@ public class ChainingAuthenticationComponentImpl implements AuthenticationCompon
/**
* 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 (ntlmMode != null)
if (this.ntlmMode != null)
{
switch (ntlmMode)
switch (this.ntlmMode)
{
case NONE:
return NTLMMode.NONE;
@@ -303,33 +272,11 @@ public class ChainingAuthenticationComponentImpl implements AuthenticationCompon
}
}
/**
* Get the system user name
*/
public String getSystemUserName()
{
return AuthenticationUtil.SYSTEM_USER_NAME;
}
/**
* If any implementation supports System then System is allowed
*/
public boolean isSystemUserName(String userName)
{
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
if (authComponent.isSystemUserName(userName))
{
return true;
}
}
return false;
}
/**
* If any implementation supports guest then guest is allowed
*/
public boolean guestUserAuthenticationAllowed()
@Override
protected boolean implementationAllowsGuestLogin()
{
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
@@ -341,16 +288,7 @@ public class ChainingAuthenticationComponentImpl implements AuthenticationCompon
return false;
}
/**
* Ste the current authentication
*/
public Authentication setCurrentAuthentication(Authentication authentication)
{
return AuthenticationUtil.setFullAuthentication(authentication);
}
@Override
public Authentication setCurrentUser(String userName, UserNameValidationMode validationMode)
{
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
@@ -370,6 +308,7 @@ public class ChainingAuthenticationComponentImpl implements AuthenticationCompon
/**
* Set the current user - try all implementations - as some may check the user exists
*/
@Override
public Authentication setCurrentUser(String userName)
{
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
@@ -386,33 +325,6 @@ public class ChainingAuthenticationComponentImpl implements AuthenticationCompon
throw new AuthenticationException("Failed to set current user " + userName);
}
/**
* Authenticate as guest - try all in the cahin
*/
public Authentication setGuestUserAsCurrentUser()
{
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
try
{
return authComponent.setGuestUserAsCurrentUser();
}
catch (AuthenticationException e)
{
// Ignore and chain
}
}
throw new AuthenticationException("Guest authentication is not allowed");
}
/**
* Set the system user
*/
public Authentication setSystemUserAsCurrentUser()
{
return setCurrentUser(getSystemUserName());
}
/**
* Helper to get authentication components
*
@@ -420,33 +332,20 @@ public class ChainingAuthenticationComponentImpl implements AuthenticationCompon
*/
private List<AuthenticationComponent> getUsableAuthenticationComponents()
{
if (mutableAuthenticationComponent == null)
if (this.mutableAuthenticationComponent == null)
{
return authenticationComponents;
return this.authenticationComponents;
}
else
{
ArrayList<AuthenticationComponent> services = new ArrayList<AuthenticationComponent>(authenticationComponents == null ? 1 : (authenticationComponents.size() + 1));
services.add(mutableAuthenticationComponent);
if (authenticationComponents != null)
ArrayList<AuthenticationComponent> services = new ArrayList<AuthenticationComponent>(
this.authenticationComponents == null ? 1 : this.authenticationComponents.size() + 1);
services.add(this.mutableAuthenticationComponent);
if (this.authenticationComponents != null)
{
services.addAll(authenticationComponents);
services.addAll(this.authenticationComponents);
}
return services;
}
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.security.authentication.AuthenticationComponent#getDefaultAdministratorUserNames()
*/
public Set<String> getDefaultAdministratorUserNames()
{
Set<String> defaultAdministratorUserNames = new TreeSet<String>();
for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
{
defaultAdministratorUserNames.addAll(authComponent.getDefaultAdministratorUserNames());
}
return defaultAdministratorUserNames;
}
}