Improve system authenticated bean post-processing
authorMathieu Baudier <mbaudier@argeo.org>
Wed, 20 Apr 2011 11:47:12 +0000 (11:47 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Wed, 20 Apr 2011 11:47:12 +0000 (11:47 +0000)
ASSIGNED - bug 17: Generalize agent management and registration beyond JMS
https://bugzilla.argeo.org/show_bug.cgi?id=17

git-svn-id: https://svn.argeo.org/commons/trunk@4464 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/AbstractSystemExecution.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/SystemExecutionBeanPostProcessor.java

index 55f0fefcc156c9bd37d3c5c186f0657f3ce1cc8d..23a111b9430e51e50c5c5b507a560c7514ed2bde 100644 (file)
@@ -4,6 +4,8 @@ import java.security.AccessController;
 
 import javax.security.auth.Subject;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.argeo.ArgeoException;
 import org.springframework.security.Authentication;
 import org.springframework.security.AuthenticationManager;
@@ -12,14 +14,25 @@ import org.springframework.security.context.SecurityContextHolder;
 
 /** Provides base method for executing code with system authorization. */
 public abstract class AbstractSystemExecution {
+       private final static Log log = LogFactory
+                       .getLog(AbstractSystemExecution.class);
        private AuthenticationManager authenticationManager;
        private String systemAuthenticationKey;
 
+       /** Whether the current thread was authenticated by this component. */
+       private ThreadLocal<Boolean> authenticatedBySelf = new ThreadLocal<Boolean>() {
+               protected Boolean initialValue() {
+                       return false;
+               }
+       };
+
        /**
         * Authenticate the calling thread to the underlying
         * {@link AuthenticationManager}
         */
        protected void authenticateAsSystem() {
+               if (authenticatedBySelf.get())
+                       return;
                SecurityContext securityContext = SecurityContextHolder.getContext();
                Authentication currentAuth = securityContext.getAuthentication();
                if (currentAuth != null)
@@ -43,13 +56,21 @@ public abstract class AbstractSystemExecution {
                Authentication auth = authenticationManager
                                .authenticate(new InternalAuthentication(key));
                securityContext.setAuthentication(auth);
+               authenticatedBySelf.set(true);
+               if (log.isTraceEnabled())
+                       log.trace("System authenticated");
        }
 
        /** Removes the authentication from the calling thread. */
        protected void deauthenticateAsSystem() {
                // remove the authentication
                SecurityContext securityContext = SecurityContextHolder.getContext();
-               securityContext.setAuthentication(null);
+               if (securityContext.getAuthentication() != null) {
+                       securityContext.setAuthentication(null);
+                       authenticatedBySelf.set(false);
+                       if (log.isTraceEnabled())
+                               log.trace("System deauthenticated");
+               }
        }
 
        public void setAuthenticationManager(
index 017317361f9c70ce067172238872bf1534581365..a2086bb9cda28918152c01fe6b31db07d8a0ba9b 100644 (file)
@@ -1,14 +1,38 @@
 package org.argeo.security.core;
 
+import java.beans.PropertyDescriptor;
+
 import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.beans.PropertyValues;
+import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextRefreshedEvent;
 
 /**
- * Executes with a system authentication the initialization methods of the
- * application context where it has been defined.
+ * Executes with a system authentication the instantiation and initialization
+ * methods of the application context where it has been defined.
  */
-public class SystemExecutionBeanPostProcessor extends
-               AbstractSystemExecution implements BeanPostProcessor {
+public class SystemExecutionBeanPostProcessor extends AbstractSystemExecution
+               implements InstantiationAwareBeanPostProcessor, ApplicationListener {
+
+       @SuppressWarnings("rawtypes")
+       public Object postProcessBeforeInstantiation(Class beanClass,
+                       String beanName) throws BeansException {
+               authenticateAsSystem();
+               return null;
+       }
+
+       public boolean postProcessAfterInstantiation(Object bean, String beanName)
+                       throws BeansException {
+               return true;
+       }
+
+       public PropertyValues postProcessPropertyValues(PropertyValues pvs,
+                       PropertyDescriptor[] pds, Object bean, String beanName)
+                       throws BeansException {
+               return pvs;
+       }
 
        public Object postProcessBeforeInitialization(Object bean, String beanName)
                        throws BeansException {
@@ -26,4 +50,12 @@ public class SystemExecutionBeanPostProcessor extends
                return bean;
        }
 
+       public void onApplicationEvent(ApplicationEvent event) {
+               if (event instanceof ContextRefreshedEvent) {
+                       // make sure that we have deauthenticated after the application
+                       // context was initialized/refreshed
+                       deauthenticateAsSystem();
+               }
+       }
+
 }