]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/AbstractSystemExecution.java
Improve secure logging
[lgpl/argeo-commons.git] / security / runtime / org.argeo.security.core / src / main / java / org / argeo / security / core / AbstractSystemExecution.java
index 55f0fefcc156c9bd37d3c5c186f0657f3ce1cc8d..b12629ab90ca64313ecb72317fae5408e5dd8296 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,22 +14,42 @@ import org.springframework.security.context.SecurityContextHolder;
 
 /** Provides base method for executing code with system authorization. */
 public abstract class AbstractSystemExecution {
+       static {
+               // Forces Spring Security to use inheritable strategy
+               // FIXME find a better place for forcing spring security mode
+               // doesn't work for the time besing
+//             if (System.getProperty(SecurityContextHolder.SYSTEM_PROPERTY) == null)
+//                     SecurityContextHolder
+//                                     .setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
+       }
+
+       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 InheritableThreadLocal<Boolean> authenticatedBySelf = new InheritableThreadLocal<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)
+               if (currentAuth != null){
                        throw new ArgeoException(
                                        "System execution on an already authenticated thread: "
                                                        + currentAuth + ", THREAD="
                                                        + Thread.currentThread().getId());
-
+               }
                Subject subject = Subject.getSubject(AccessController.getContext());
                if (subject != null
                                && !subject.getPrincipals(Authentication.class).isEmpty())
@@ -43,13 +65,31 @@ 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");
+                               // Thread.dumpStack();
+                       }
+               }
+       }
+
+       /**
+        * Whether the current thread was authenticated by this component or a
+        * parent thread.
+        */
+       protected Boolean isAuthenticatedBySelf() {
+               return authenticatedBySelf.get();
        }
 
        public void setAuthenticationManager(