diff --git a/config/alfresco/bootstrap-context.xml b/config/alfresco/bootstrap-context.xml index d516af35c2..df272fc08c 100644 --- a/config/alfresco/bootstrap-context.xml +++ b/config/alfresco/bootstrap-context.xml @@ -32,8 +32,11 @@ --> - ${shutdown.backstop.timeout} + ${shutdown.backstop.timeout} + + ${shutdown.backstop.enabled} + diff --git a/config/alfresco/repository.properties b/config/alfresco/repository.properties index cf83b9364a..cb4e1463b4 100644 --- a/config/alfresco/repository.properties +++ b/config/alfresco/repository.properties @@ -60,6 +60,7 @@ system.bootstrap.config_check.strict=true # in ms, 10,000 is 10 seconds # shutdown.backstop.timeout=10000 +shutdown.backstop.enabled=true # Server Single User Mode # note: diff --git a/source/java/org/alfresco/repo/security/authentication/AlfrescoSecureContextImpl.java b/source/java/org/alfresco/repo/security/authentication/AlfrescoSecureContextImpl.java index cff606a330..896fb651ae 100644 --- a/source/java/org/alfresco/repo/security/authentication/AlfrescoSecureContextImpl.java +++ b/source/java/org/alfresco/repo/security/authentication/AlfrescoSecureContextImpl.java @@ -35,11 +35,11 @@ import net.sf.acegisecurity.context.ContextInvalidException; */ public class AlfrescoSecureContextImpl implements AlfrescoSecureContext { - Authentication storedAuthentication; + private Authentication storedAuthentication; - Authentication realAuthentication; + private Authentication realAuthentication; - Authentication effectiveAuthentication; + private Authentication effectiveAuthentication; /** * ACEGI @@ -55,7 +55,6 @@ public class AlfrescoSecureContextImpl implements AlfrescoSecureContext public void setAuthentication(Authentication newAuthentication) { setEffectiveAuthentication(newAuthentication); - setRealAuthentication(newAuthentication); } /** diff --git a/source/java/org/alfresco/repo/security/authentication/AuthenticationTest.java b/source/java/org/alfresco/repo/security/authentication/AuthenticationTest.java index a704f009cd..bc48a802c0 100644 --- a/source/java/org/alfresco/repo/security/authentication/AuthenticationTest.java +++ b/source/java/org/alfresco/repo/security/authentication/AuthenticationTest.java @@ -48,6 +48,7 @@ import net.sf.acegisecurity.providers.dao.SaltSource; import org.alfresco.model.ContentModel; import org.alfresco.repo.cache.SimpleCache; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.InMemoryTicketComponentImpl.ExpiryMode; import org.alfresco.repo.security.authentication.InMemoryTicketComponentImpl.Ticket; import org.alfresco.repo.tenant.TenantService; @@ -58,6 +59,7 @@ import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.namespace.DynamicNamespacePrefixResolver; import org.alfresco.service.namespace.NamespacePrefixResolver; import org.alfresco.service.namespace.NamespaceService; @@ -109,6 +111,12 @@ public class AuthenticationTest extends TestCase private AuthenticationComponent authenticationComponentImpl; + private TransactionService transactionService; + + private PersonService pubPersonService; + + private PersonService personService; + public AuthenticationTest() { super(); @@ -132,6 +140,8 @@ public class AuthenticationTest extends TestCase pubAuthenticationService = (AuthenticationService) ctx.getBean("AuthenticationService"); authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent"); authenticationComponentImpl = (AuthenticationComponent) ctx.getBean("authenticationComponent"); + pubPersonService = (PersonService) ctx.getBean("PersonService"); + personService = (PersonService) ctx.getBean("personService"); // permissionServiceSPI = (PermissionServiceSPI) // ctx.getBean("permissionService"); ticketsCache = (SimpleCache) ctx.getBean("ticketsCache"); @@ -140,7 +150,7 @@ public class AuthenticationTest extends TestCase authenticationManager = (AuthenticationManager) ctx.getBean("authenticationManager"); saltSource = (SaltSource) ctx.getBean("saltSource"); - TransactionService transactionService = (TransactionService) ctx.getBean(ServiceRegistry.TRANSACTION_SERVICE.getLocalName()); + transactionService = (TransactionService) ctx.getBean(ServiceRegistry.TRANSACTION_SERVICE.getLocalName()); userTransaction = transactionService.getUserTransaction(); userTransaction.begin(); @@ -176,6 +186,12 @@ public class AuthenticationTest extends TestCase { dao.deleteUser("andy"); } + + if(personService.personExists("andy")) + { + personService.deletePerson("andy"); + } + } @Override @@ -193,6 +209,76 @@ public class AuthenticationTest extends TestCase return properties; } + public void testSystemTicket() throws Exception + { + assertNull(AuthenticationUtil.getCurrentRealAuthentication()); + assertNull(AuthenticationUtil.getCurrentEffectiveAuthentication()); + assertNull(AuthenticationUtil.getCurrentStoredAuthentication()); + + + authenticationComponent.setSystemUserAsCurrentUser(); + pubAuthenticationService.createAuthentication("andy", "andy".toCharArray()); + + pubAuthenticationService.clearCurrentSecurityContext(); + + assertNull(AuthenticationUtil.getCurrentRealAuthentication()); + assertNull(AuthenticationUtil.getCurrentEffectiveAuthentication()); + assertNull(AuthenticationUtil.getCurrentStoredAuthentication()); + + // Authenticate + pubAuthenticationService.authenticate("andy", "andy".toCharArray()); + + // Get current user name + String userName = pubAuthenticationService.getCurrentUserName(); + assertEquals("andy", userName); + + // Get ticket + String ticket = pubAuthenticationService.getCurrentTicket(); + assertEquals("andy", ticketComponent.getAuthorityForTicket(ticket)); + + // Get logged in user ... + // Get userName + userName = pubAuthenticationService.getCurrentUserName(); + assertEquals("andy", userName); + // get Person + assertFalse(pubPersonService.personExists(userName)); + + AuthenticationUtil.runAs(new RunAsWork() { + + public Object doWork() throws Exception + { + // TODO Auto-generated method stub + assertEquals("andy", ticketComponent.getAuthorityForTicket(pubAuthenticationService.getCurrentTicket())); + return null; + }}, AuthenticationUtil.getSystemUserName()); + + pubPersonService.getPerson(userName); + assertTrue(pubPersonService.personExists(userName)); + // re-getTicket + String newticket = pubAuthenticationService.getCurrentTicket(); + assertEquals(ticket, newticket); + assertEquals("andy", ticketComponent.getAuthorityForTicket(newticket)); + + + userName = pubAuthenticationService.getCurrentUserName(); + assertEquals("andy", userName); + + // new TX + + userTransaction.commit(); + userTransaction = transactionService.getUserTransaction(); + userTransaction.begin(); + + pubAuthenticationService.validate(ticket); + userName = pubAuthenticationService.getCurrentUserName(); + assertEquals("andy", userName); + + pubAuthenticationService.validate(newticket); + userName = pubAuthenticationService.getCurrentUserName(); + assertEquals("andy", userName); + + } + public void xtestScalability() { long create = 0; diff --git a/source/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java b/source/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java index b46b57445a..b70d9b6a30 100644 --- a/source/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java +++ b/source/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java @@ -30,17 +30,18 @@ import net.sf.acegisecurity.GrantedAuthorityImpl; import net.sf.acegisecurity.UserDetails; import net.sf.acegisecurity.context.Context; import net.sf.acegisecurity.context.ContextHolder; -import net.sf.acegisecurity.context.security.SecureContext; -import net.sf.acegisecurity.context.security.SecureContextImpl; 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; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.log4j.NDC; public abstract class AuthenticationUtil { + static Log s_logger = LogFactory.getLog(AuthenticationUtil.class); public interface RunAsWork { @@ -249,7 +250,8 @@ public abstract class AuthenticationUtil } authentication.setAuthenticated(true); // Sets real and effective - sc.setAuthentication(authentication); + sc.setRealAuthentication(authentication); + sc.setEffectiveAuthentication(authentication); // Support for logging tenant domain / username (via log4j NDC) String userName = SYSTEM_USER_NAME; @@ -606,7 +608,13 @@ public abstract class AuthenticationUtil } else { + if(!AuthenticationUtil.getCurrentRealUserName().equals(realUser)) + { + AuthenticationUtil.setCurrentRealUser(realUser); + s_logger.warn("Resetting real user which has changed in RunAs block"); + } AuthenticationUtil.setCurrentEffectiveUser(effectiveUser); + } } } diff --git a/source/java/org/alfresco/repo/shutdown/ShutdownBackstop.java b/source/java/org/alfresco/repo/shutdown/ShutdownBackstop.java index 5055bc2274..d3145e286e 100644 --- a/source/java/org/alfresco/repo/shutdown/ShutdownBackstop.java +++ b/source/java/org/alfresco/repo/shutdown/ShutdownBackstop.java @@ -54,6 +54,11 @@ public class ShutdownBackstop extends AbstractLifecycleBean */ private int timeout = 10000; + /** + * is the backstop enabled? + */ + private boolean enabled = true; + protected final static Log log = LogFactory.getLog(ShutdownBackstop.class); public void setTimeout(int timeout) { @@ -79,11 +84,22 @@ public class ShutdownBackstop extends AbstractLifecycleBean @Override protected void onShutdown(ApplicationEvent event) { - log.info("Shutdown backstop timer started"); - Thread selfDestructThread = new ShutdownBackstopThread(timeout); - selfDestructThread.start(); + if(isEnabled()) + { + log.info("Shutdown backstop timer started"); + Thread selfDestructThread = new ShutdownBackstopThread(timeout); + selfDestructThread.start(); + } } + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public boolean isEnabled() { + return enabled; + } + /** * This is a dangerous class! It will kill the JVM after sleeping * for timeout ms.