mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-08 14:51:49 +00:00
Merged 5.1-MC1 (5.1.0) to HEAD (5.1)
119057 adavis: Merged 5.1.N (5.1.1) to 5.1-MC1 (5.1.0) 117339 adavis: Merged 5.0.2-CLOUD42 (Cloud ) to 5.1.N (5.1.1) 117247 adavis: Merged 5.0.2-CLOUD (Cloud ) to 5.0.2-CLOUD42 (Cloud ) 114516 adavis: Merged BCRYPT to 5.0.2-CLOUD 114004 gjames: Added a hashUserPassword method, and working on UpgradePasswordHashTest MNT-14892 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@119896 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -41,6 +41,7 @@ import org.springframework.dao.DataAccessException;
|
|||||||
* getMD4HashedPassword(String userName)
|
* getMD4HashedPassword(String userName)
|
||||||
* loadUserByUsername(String arg0)
|
* loadUserByUsername(String arg0)
|
||||||
* getSalt(UserDetails user)
|
* getSalt(UserDetails user)
|
||||||
|
* hashUserPassword(String userName)
|
||||||
*
|
*
|
||||||
* @author Andy Hind
|
* @author Andy Hind
|
||||||
*/
|
*/
|
||||||
@@ -385,6 +386,14 @@ public class DefaultMutableAuthenticationDao implements MutableAuthenticationDao
|
|||||||
throw new AlfrescoRuntimeException("Not implemented");
|
throw new AlfrescoRuntimeException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AlfrescoRuntimeException always
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void hashUserPassword(String userName) throws AuthenticationException
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
// -------- //
|
// -------- //
|
||||||
// Bean IOC //
|
// Bean IOC //
|
||||||
|
@@ -51,6 +51,11 @@ public interface MutableAuthenticationDao extends AuthenticationDao, SaltSource
|
|||||||
*/
|
*/
|
||||||
public boolean userExists(String userName);
|
public boolean userExists(String userName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hashes the user password to the preferred encoding.
|
||||||
|
*/
|
||||||
|
public void hashUserPassword(String userName) throws AuthenticationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable/disable a user.
|
* Enable/disable a user.
|
||||||
*/
|
*/
|
||||||
|
@@ -469,6 +469,22 @@ public class RepositoryAuthenticationDao implements MutableAuthenticationDao, In
|
|||||||
return (getUserOrNull(userName) != null);
|
return (getUserOrNull(userName) != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hashUserPassword(String userName) throws AuthenticationException
|
||||||
|
{
|
||||||
|
NodeRef userRef = getUserOrNull(userName);
|
||||||
|
if (userRef == null)
|
||||||
|
{
|
||||||
|
throw new AuthenticationException("User name does not exist: " + userName);
|
||||||
|
}
|
||||||
|
Map<QName, Serializable> properties = nodeService.getProperties(userRef);
|
||||||
|
|
||||||
|
if (rehashedPassword(properties))
|
||||||
|
{
|
||||||
|
nodeService.setProperties(userRef, properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Returns the user properties or <tt>null</tt> if there are none
|
* @return Returns the user properties or <tt>null</tt> if there are none
|
||||||
*/
|
*/
|
||||||
|
@@ -42,6 +42,7 @@ import org.alfresco.repo.lock.LockAcquisitionException;
|
|||||||
import org.alfresco.repo.policy.BehaviourFilter;
|
import org.alfresco.repo.policy.BehaviourFilter;
|
||||||
import org.alfresco.repo.site.SiteModel;
|
import org.alfresco.repo.site.SiteModel;
|
||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.service.transaction.TransactionService;
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
@@ -278,6 +279,18 @@ public class UpgradePasswordHashWorker implements ApplicationContextAware, Initi
|
|||||||
RetryingTransactionHelper retryingTransactionHelper = transactionService.getRetryingTransactionHelper();
|
RetryingTransactionHelper retryingTransactionHelper = transactionService.getRetryingTransactionHelper();
|
||||||
retryingTransactionHelper.setForceWritable(true);
|
retryingTransactionHelper.setForceWritable(true);
|
||||||
|
|
||||||
|
//Create the QNames if they don't exist
|
||||||
|
retryingTransactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
qnameDAO.getOrCreateQName(ContentModel.PROP_PASSWORD_HASH);
|
||||||
|
qnameDAO.getOrCreateQName(ContentModel.PROP_HASH_INDICATOR);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, false, true);
|
||||||
|
|
||||||
BatchProcessor<Long> batchProcessor = new BatchProcessor<Long>(
|
BatchProcessor<Long> batchProcessor = new BatchProcessor<Long>(
|
||||||
"UpgradePasswordHashWorker",
|
"UpgradePasswordHashWorker",
|
||||||
retryingTransactionHelper,
|
retryingTransactionHelper,
|
||||||
@@ -399,15 +412,12 @@ public class UpgradePasswordHashWorker implements ApplicationContextAware, Initi
|
|||||||
// We do not want any behaviours associated with our transactions
|
// We do not want any behaviours associated with our transactions
|
||||||
behaviourFilter.disableBehaviour();
|
behaviourFilter.disableBehaviour();
|
||||||
|
|
||||||
// call hashedPassword on the RepositoryAuthenticationDao object
|
|
||||||
|
|
||||||
|
|
||||||
// ((RepositoryAuthenticationDao)authenticationDao).rehashedPassword(userProps);
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
logger.debug("Upgrading password hash for user: " + username);
|
logger.debug("Upgrading password hash for user: " + username);
|
||||||
}
|
}
|
||||||
|
authenticationDao.hashUserPassword(username);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (logger.isTraceEnabled())
|
else if (logger.isTraceEnabled())
|
||||||
{
|
{
|
||||||
|
@@ -237,6 +237,15 @@ public class NullMutableAuthenticationDao implements MutableAuthenticationDao
|
|||||||
throw new AlfrescoRuntimeException("Not implemented");
|
throw new AlfrescoRuntimeException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AlfrescoRuntimeException always
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void hashUserPassword(String userName) throws AuthenticationException
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws AlfrescoRuntimeException Not implemented
|
* @throws AlfrescoRuntimeException Not implemented
|
||||||
*/
|
*/
|
||||||
|
@@ -18,8 +18,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.security.authentication;
|
package org.alfresco.repo.security.authentication;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.transaction.Status;
|
import javax.transaction.Status;
|
||||||
import javax.transaction.UserTransaction;
|
import javax.transaction.UserTransaction;
|
||||||
@@ -27,11 +31,20 @@ import javax.transaction.UserTransaction;
|
|||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.cache.SimpleCache;
|
||||||
|
import org.alfresco.repo.policy.PolicyComponent;
|
||||||
|
import org.alfresco.repo.tenant.TenantService;
|
||||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
|
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
|
||||||
import org.alfresco.service.ServiceRegistry;
|
import org.alfresco.service.ServiceRegistry;
|
||||||
|
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.test_category.OwnJVMTestsCategory;
|
import org.alfresco.test_category.OwnJVMTestsCategory;
|
||||||
import org.alfresco.util.ApplicationContextHelper;
|
import org.alfresco.util.ApplicationContextHelper;
|
||||||
|
import org.alfresco.util.GUID;
|
||||||
import org.junit.experimental.categories.Category;
|
import org.junit.experimental.categories.Category;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
@@ -43,9 +56,12 @@ public class UpgradePasswordHashTest extends TestCase
|
|||||||
|
|
||||||
private UserTransaction userTransaction;
|
private UserTransaction userTransaction;
|
||||||
private ServiceRegistry serviceRegistry;
|
private ServiceRegistry serviceRegistry;
|
||||||
|
private NodeService nodeService;
|
||||||
|
private RepositoryAuthenticationDao repositoryAuthenticationDao;
|
||||||
|
private CompositePasswordEncoder compositePasswordEncoder;
|
||||||
private UpgradePasswordHashWorker upgradePasswordHashWorker;
|
private UpgradePasswordHashWorker upgradePasswordHashWorker;
|
||||||
private List<String> testUserNames;
|
private List<String> testUserNames;
|
||||||
|
private List<NodeRef> testUsers;
|
||||||
public UpgradePasswordHashTest()
|
public UpgradePasswordHashTest()
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
@@ -67,27 +83,86 @@ public class UpgradePasswordHashTest extends TestCase
|
|||||||
|
|
||||||
serviceRegistry = (ServiceRegistry)ctx.getBean("ServiceRegistry");
|
serviceRegistry = (ServiceRegistry)ctx.getBean("ServiceRegistry");
|
||||||
|
|
||||||
upgradePasswordHashWorker = (UpgradePasswordHashWorker)ctx.getBean("upgradePasswordHashWorker");
|
SimpleCache<String, RepositoryAuthenticationDao.CacheEntry> authenticationCache = (SimpleCache<String, RepositoryAuthenticationDao.CacheEntry>) ctx.getBean("authenticationCache");
|
||||||
|
SimpleCache<String, NodeRef> immutableSingletonCache = (SimpleCache<String, NodeRef>) ctx.getBean("immutableSingletonCache");
|
||||||
|
TenantService tenantService = (TenantService) ctx.getBean("tenantService");
|
||||||
|
compositePasswordEncoder = (CompositePasswordEncoder) ctx.getBean("compositePasswordEncoder");
|
||||||
|
PolicyComponent policyComponent = (PolicyComponent) ctx.getBean("policyComponent");
|
||||||
|
|
||||||
|
repositoryAuthenticationDao = new RepositoryAuthenticationDao();
|
||||||
|
repositoryAuthenticationDao.setTransactionService(serviceRegistry.getTransactionService());
|
||||||
|
repositoryAuthenticationDao.setAuthorityService(serviceRegistry.getAuthorityService());
|
||||||
|
repositoryAuthenticationDao.setTenantService(tenantService);
|
||||||
|
repositoryAuthenticationDao.setNodeService(serviceRegistry.getNodeService());
|
||||||
|
repositoryAuthenticationDao.setNamespaceService(serviceRegistry.getNamespaceService());
|
||||||
|
repositoryAuthenticationDao.setCompositePasswordEncoder(compositePasswordEncoder);
|
||||||
|
repositoryAuthenticationDao.setPolicyComponent(policyComponent);
|
||||||
|
repositoryAuthenticationDao.setAuthenticationCache(authenticationCache);
|
||||||
|
repositoryAuthenticationDao.setSingletonCache(immutableSingletonCache);
|
||||||
|
|
||||||
|
upgradePasswordHashWorker = (UpgradePasswordHashWorker)ctx.getBean("upgradePasswordHashWorker");
|
||||||
|
nodeService = serviceRegistry.getNodeService();
|
||||||
userTransaction = serviceRegistry.getTransactionService().getUserTransaction();
|
userTransaction = serviceRegistry.getTransactionService().getUserTransaction();
|
||||||
userTransaction.begin();
|
userTransaction.begin();
|
||||||
|
|
||||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
||||||
|
|
||||||
createTestUsers();
|
createTestUsers("md4");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void createTestUsers() throws Exception
|
protected void createTestUsers(String encoding) throws Exception
|
||||||
{
|
{
|
||||||
|
|
||||||
// create 50 users and change their properties back to how
|
// create 50 users and change their properties back to how
|
||||||
// they would have been pre-upgrade.
|
// they would have been pre-upgrade.
|
||||||
|
testUsers = new ArrayList<NodeRef>(50);
|
||||||
|
testUsers.add(createUser("king"+encoding, "king".toCharArray(), encoding));
|
||||||
|
testUsers.add(createUser("kin" +encoding, "Kong".toCharArray(), encoding));
|
||||||
|
testUsers.add(createUser("ding"+encoding, "dong".toCharArray(), encoding));
|
||||||
|
testUsers.add(createUser("ping"+encoding, "pong".toCharArray(),encoding));
|
||||||
|
testUsers.add(createUser("pin" +encoding, "pop".toCharArray(), encoding));
|
||||||
|
}
|
||||||
|
|
||||||
testUserNames = new ArrayList<String>(50);
|
private NodeRef createUser(String caseSensitiveUserName, char[] password, String encoding)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
repositoryAuthenticationDao.createUser(caseSensitiveUserName,password);
|
||||||
|
} catch (AuthenticationException e)
|
||||||
|
{
|
||||||
|
if (!e.getMessage().contains("User already exists")) { throw e; }
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeRef userNodeRef = repositoryAuthenticationDao.getUserOrNull(caseSensitiveUserName);
|
||||||
|
if (userNodeRef == null)
|
||||||
|
{
|
||||||
|
throw new AuthenticationException("User name does not exist: " + caseSensitiveUserName);
|
||||||
|
}
|
||||||
|
Map<QName, Serializable> properties = nodeService.getProperties(userNodeRef);
|
||||||
|
properties.remove(ContentModel.PROP_PASSWORD_HASH);
|
||||||
|
properties.remove(ContentModel.PROP_HASH_INDICATOR);
|
||||||
|
properties.remove(ContentModel.PROP_PASSWORD);
|
||||||
|
properties.remove(ContentModel.PROP_PASSWORD_SHA256);
|
||||||
|
properties.put(ContentModel.PROP_PASSWORD, compositePasswordEncoder.encode(encoding,new String(password), null));
|
||||||
|
nodeService.setProperties(userNodeRef, properties);
|
||||||
|
return userNodeRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void deleteTestUsers() throws Exception
|
protected void deleteTestUsers() throws Exception
|
||||||
{
|
{
|
||||||
// delete all the test users.
|
for (NodeRef testUser : testUsers)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
nodeService.deleteNode(testUser);
|
||||||
|
}
|
||||||
|
catch (InvalidNodeRefException e)
|
||||||
|
{
|
||||||
|
//Just ignore it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testUsers.clear();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -108,10 +183,24 @@ public class UpgradePasswordHashTest extends TestCase
|
|||||||
|
|
||||||
public void testWorkerWithDefaultConfiguration() throws Exception
|
public void testWorkerWithDefaultConfiguration() throws Exception
|
||||||
{
|
{
|
||||||
|
for (NodeRef testUser : testUsers)
|
||||||
|
{
|
||||||
|
assertNull("The hash indicator should not be set",nodeService.getProperty(testUser, ContentModel.PROP_HASH_INDICATOR));
|
||||||
|
assertNull("The password hash should not be set",nodeService.getProperty(testUser, ContentModel.PROP_PASSWORD_HASH));
|
||||||
|
}
|
||||||
// execute the worker to upgrade all users
|
// execute the worker to upgrade all users
|
||||||
this.upgradePasswordHashWorker.execute();
|
this.upgradePasswordHashWorker.execute();
|
||||||
|
|
||||||
// ensure all the test users have been upgraded to use the preferred encoding
|
// ensure all the test users have been upgraded to use the preferred encoding
|
||||||
|
List<String> doubleHashed = Arrays.asList("md4", "bcrypt10");
|
||||||
|
for (NodeRef testUser : testUsers)
|
||||||
|
{
|
||||||
|
assertNotNull("The password hash should be set", nodeService.getProperty(testUser, ContentModel.PROP_PASSWORD_HASH));
|
||||||
|
assertEquals(doubleHashed,nodeService.getProperty(testUser, ContentModel.PROP_HASH_INDICATOR));
|
||||||
|
assertNull("The md4 password should not be set", nodeService.getProperty(testUser, ContentModel.PROP_PASSWORD));
|
||||||
|
assertNull("The sh256 password should not be set",nodeService.getProperty(testUser, ContentModel.PROP_PASSWORD_SHA256));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void xxxtestWorkerWithLegacyConfiguration() throws Exception
|
public void xxxtestWorkerWithLegacyConfiguration() throws Exception
|
||||||
|
Reference in New Issue
Block a user