|  | @@ -132,6 +132,9 @@ import org.springframework.util.Assert;
 | 
	
		
			
				|  |  |   * </li>
 | 
	
		
			
				|  |  |   * </ol>
 | 
	
		
			
				|  |  |   * </p>
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * @author Ben Alex
 | 
	
		
			
				|  |  | + * @version $Id$
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  public abstract class AbstractSecurityInterceptor implements InitializingBean,
 | 
	
		
			
				|  |  |      ApplicationEventPublisherAware, MessageSourceAware {
 | 
	
	
		
			
				|  | @@ -189,342 +192,342 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean,
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              return returnedObject;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public void afterPropertiesSet() throws Exception {
 | 
	
		
			
				|  |  | -            Assert.notNull(getSecureObjectClass(),
 | 
	
		
			
				|  |  | -                "Subclass must provide a non-null response to getSecureObjectClass()");
 | 
	
		
			
				|  |  | +    public void afterPropertiesSet() throws Exception {
 | 
	
		
			
				|  |  | +        Assert.notNull(getSecureObjectClass(),
 | 
	
		
			
				|  |  | +            "Subclass must provide a non-null response to getSecureObjectClass()");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            Assert.notNull(this.messages, "A message source must be set");
 | 
	
		
			
				|  |  | -            Assert.notNull(this.authenticationManager,
 | 
	
		
			
				|  |  | -                "An AuthenticationManager is required");
 | 
	
		
			
				|  |  | +        Assert.notNull(this.messages, "A message source must be set");
 | 
	
		
			
				|  |  | +        Assert.notNull(this.authenticationManager,
 | 
	
		
			
				|  |  | +            "An AuthenticationManager is required");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            Assert.notNull(this.accessDecisionManager,
 | 
	
		
			
				|  |  | -                "An AccessDecisionManager is required");
 | 
	
		
			
				|  |  | +        Assert.notNull(this.accessDecisionManager,
 | 
	
		
			
				|  |  | +            "An AccessDecisionManager is required");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            Assert.notNull(this.runAsManager, "A RunAsManager is required");
 | 
	
		
			
				|  |  | +        Assert.notNull(this.runAsManager, "A RunAsManager is required");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            Assert.notNull(this.obtainObjectDefinitionSource(),
 | 
	
		
			
				|  |  | -                "An ObjectDefinitionSource is required");
 | 
	
		
			
				|  |  | +        Assert.notNull(this.obtainObjectDefinitionSource(),
 | 
	
		
			
				|  |  | +            "An ObjectDefinitionSource is required");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if (!this.obtainObjectDefinitionSource()
 | 
	
		
			
				|  |  | -                     .supports(getSecureObjectClass())) {
 | 
	
		
			
				|  |  | -                throw new IllegalArgumentException(
 | 
	
		
			
				|  |  | -                    "ObjectDefinitionSource does not support secure object class: "
 | 
	
		
			
				|  |  | -                    + getSecureObjectClass());
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +        if (!this.obtainObjectDefinitionSource()
 | 
	
		
			
				|  |  | +                 .supports(getSecureObjectClass())) {
 | 
	
		
			
				|  |  | +            throw new IllegalArgumentException(
 | 
	
		
			
				|  |  | +                "ObjectDefinitionSource does not support secure object class: "
 | 
	
		
			
				|  |  | +                + getSecureObjectClass());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if (!this.runAsManager.supports(getSecureObjectClass())) {
 | 
	
		
			
				|  |  | -                throw new IllegalArgumentException(
 | 
	
		
			
				|  |  | -                    "RunAsManager does not support secure object class: "
 | 
	
		
			
				|  |  | -                    + getSecureObjectClass());
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +        if (!this.runAsManager.supports(getSecureObjectClass())) {
 | 
	
		
			
				|  |  | +            throw new IllegalArgumentException(
 | 
	
		
			
				|  |  | +                "RunAsManager does not support secure object class: "
 | 
	
		
			
				|  |  | +                + getSecureObjectClass());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if (!this.accessDecisionManager.supports(getSecureObjectClass())) {
 | 
	
		
			
				|  |  | -                throw new IllegalArgumentException(
 | 
	
		
			
				|  |  | -                    "AccessDecisionManager does not support secure object class: "
 | 
	
		
			
				|  |  | -                    + getSecureObjectClass());
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +        if (!this.accessDecisionManager.supports(getSecureObjectClass())) {
 | 
	
		
			
				|  |  | +            throw new IllegalArgumentException(
 | 
	
		
			
				|  |  | +                "AccessDecisionManager does not support secure object class: "
 | 
	
		
			
				|  |  | +                + getSecureObjectClass());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if ((this.afterInvocationManager != null)
 | 
	
		
			
				|  |  | -                && !this.afterInvocationManager.supports(getSecureObjectClass())) {
 | 
	
		
			
				|  |  | -                throw new IllegalArgumentException(
 | 
	
		
			
				|  |  | -                    "AfterInvocationManager does not support secure object class: "
 | 
	
		
			
				|  |  | -                    + getSecureObjectClass());
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +        if ((this.afterInvocationManager != null)
 | 
	
		
			
				|  |  | +            && !this.afterInvocationManager.supports(getSecureObjectClass())) {
 | 
	
		
			
				|  |  | +            throw new IllegalArgumentException(
 | 
	
		
			
				|  |  | +                "AfterInvocationManager does not support secure object class: "
 | 
	
		
			
				|  |  | +                + getSecureObjectClass());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if (this.validateConfigAttributes) {
 | 
	
		
			
				|  |  | -                Iterator iter = this.obtainObjectDefinitionSource()
 | 
	
		
			
				|  |  | -                                    .getConfigAttributeDefinitions();
 | 
	
		
			
				|  |  | +        if (this.validateConfigAttributes) {
 | 
	
		
			
				|  |  | +            Iterator iter = this.obtainObjectDefinitionSource()
 | 
	
		
			
				|  |  | +                                .getConfigAttributeDefinitions();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                if (iter == null) {
 | 
	
		
			
				|  |  | -                    if (logger.isWarnEnabled()) {
 | 
	
		
			
				|  |  | -                        logger.warn(
 | 
	
		
			
				|  |  | -                            "Could not validate configuration attributes as the MethodDefinitionSource did not return a ConfigAttributeDefinition Iterator");
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                } else {
 | 
	
		
			
				|  |  | -                    Set set = new HashSet();
 | 
	
		
			
				|  |  | +            if (iter == null) {
 | 
	
		
			
				|  |  | +                if (logger.isWarnEnabled()) {
 | 
	
		
			
				|  |  | +                    logger.warn(
 | 
	
		
			
				|  |  | +                        "Could not validate configuration attributes as the MethodDefinitionSource did not return a ConfigAttributeDefinition Iterator");
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                Set set = new HashSet();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                while (iter.hasNext()) {
 | 
	
		
			
				|  |  | +                    ConfigAttributeDefinition def = (ConfigAttributeDefinition) iter
 | 
	
		
			
				|  |  | +                        .next();
 | 
	
		
			
				|  |  | +                    Iterator attributes = def.getConfigAttributes();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    while (iter.hasNext()) {
 | 
	
		
			
				|  |  | -                        ConfigAttributeDefinition def = (ConfigAttributeDefinition) iter
 | 
	
		
			
				|  |  | +                    while (attributes.hasNext()) {
 | 
	
		
			
				|  |  | +                        ConfigAttribute attr = (ConfigAttribute) attributes
 | 
	
		
			
				|  |  |                              .next();
 | 
	
		
			
				|  |  | -                        Iterator attributes = def.getConfigAttributes();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                        while (attributes.hasNext()) {
 | 
	
		
			
				|  |  | -                            ConfigAttribute attr = (ConfigAttribute) attributes
 | 
	
		
			
				|  |  | -                                .next();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                            if (!this.runAsManager.supports(attr)
 | 
	
		
			
				|  |  | -                                && !this.accessDecisionManager.supports(attr)
 | 
	
		
			
				|  |  | -                                && ((this.afterInvocationManager == null)
 | 
	
		
			
				|  |  | -                                || !this.afterInvocationManager.supports(attr))) {
 | 
	
		
			
				|  |  | -                                set.add(attr);
 | 
	
		
			
				|  |  | -                            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                        if (!this.runAsManager.supports(attr)
 | 
	
		
			
				|  |  | +                            && !this.accessDecisionManager.supports(attr)
 | 
	
		
			
				|  |  | +                            && ((this.afterInvocationManager == null)
 | 
	
		
			
				|  |  | +                            || !this.afterInvocationManager.supports(attr))) {
 | 
	
		
			
				|  |  | +                            set.add(attr);
 | 
	
		
			
				|  |  |                          }
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    if (set.size() == 0) {
 | 
	
		
			
				|  |  | -                        if (logger.isInfoEnabled()) {
 | 
	
		
			
				|  |  | -                            logger.info("Validated configuration attributes");
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                    } else {
 | 
	
		
			
				|  |  | -                        throw new IllegalArgumentException(
 | 
	
		
			
				|  |  | -                            "Unsupported configuration attributes: "
 | 
	
		
			
				|  |  | -                            + set.toString());
 | 
	
		
			
				|  |  | +                if (set.size() == 0) {
 | 
	
		
			
				|  |  | +                    if (logger.isInfoEnabled()) {
 | 
	
		
			
				|  |  | +                        logger.info("Validated configuration attributes");
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  | +                } else {
 | 
	
		
			
				|  |  | +                    throw new IllegalArgumentException(
 | 
	
		
			
				|  |  | +                        "Unsupported configuration attributes: "
 | 
	
		
			
				|  |  | +                        + set.toString());
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        protected InterceptorStatusToken beforeInvocation(Object object) {
 | 
	
		
			
				|  |  | -            Assert.notNull(object, "Object was null");
 | 
	
		
			
				|  |  | -            Assert.isTrue(getSecureObjectClass()
 | 
	
		
			
				|  |  | -                              .isAssignableFrom(object.getClass()),
 | 
	
		
			
				|  |  | -                "Security invocation attempted for object "
 | 
	
		
			
				|  |  | -                + object.getClass().getName()
 | 
	
		
			
				|  |  | -                + " but AbstractSecurityInterceptor only configured to support secure objects of type: "
 | 
	
		
			
				|  |  | -                + getSecureObjectClass());
 | 
	
		
			
				|  |  | +    protected InterceptorStatusToken beforeInvocation(Object object) {
 | 
	
		
			
				|  |  | +        Assert.notNull(object, "Object was null");
 | 
	
		
			
				|  |  | +        Assert.isTrue(getSecureObjectClass()
 | 
	
		
			
				|  |  | +                          .isAssignableFrom(object.getClass()),
 | 
	
		
			
				|  |  | +            "Security invocation attempted for object "
 | 
	
		
			
				|  |  | +            + object.getClass().getName()
 | 
	
		
			
				|  |  | +            + " but AbstractSecurityInterceptor only configured to support secure objects of type: "
 | 
	
		
			
				|  |  | +            + getSecureObjectClass());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        ConfigAttributeDefinition attr = this.obtainObjectDefinitionSource()
 | 
	
		
			
				|  |  | +                                             .getAttributes(object);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if ((attr == null) && rejectPublicInvocations) {
 | 
	
		
			
				|  |  | +            throw new IllegalArgumentException(
 | 
	
		
			
				|  |  | +                "No public invocations are allowed via this AbstractSecurityInterceptor. This indicates a configuration error because the AbstractSecurityInterceptor.rejectPublicInvocations property is set to 'true'");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            ConfigAttributeDefinition attr = this.obtainObjectDefinitionSource()
 | 
	
		
			
				|  |  | -                                                 .getAttributes(object);
 | 
	
		
			
				|  |  | +        if (attr != null) {
 | 
	
		
			
				|  |  | +            if (logger.isDebugEnabled()) {
 | 
	
		
			
				|  |  | +                logger.debug("Secure object: " + object.toString()
 | 
	
		
			
				|  |  | +                    + "; ConfigAttributes: " + attr.toString());
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if ((attr == null) && rejectPublicInvocations) {
 | 
	
		
			
				|  |  | -                throw new IllegalArgumentException(
 | 
	
		
			
				|  |  | -                    "No public invocations are allowed via this AbstractSecurityInterceptor. This indicates a configuration error because the AbstractSecurityInterceptor.rejectPublicInvocations property is set to 'true'");
 | 
	
		
			
				|  |  | +            // We check for just the property we're interested in (we do
 | 
	
		
			
				|  |  | +            // not call Context.validate() like the ContextInterceptor)
 | 
	
		
			
				|  |  | +            if (SecurityContextHolder.getContext().getAuthentication() == null) {
 | 
	
		
			
				|  |  | +                credentialsNotFound(messages.getMessage(
 | 
	
		
			
				|  |  | +                        "AbstractSecurityInterceptor.authenticationNotFound",
 | 
	
		
			
				|  |  | +                        "An Authentication object was not found in the SecurityContext"),
 | 
	
		
			
				|  |  | +                    object, attr);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if (attr != null) {
 | 
	
		
			
				|  |  | -                if (logger.isDebugEnabled()) {
 | 
	
		
			
				|  |  | -                    logger.debug("Secure object: " + object.toString()
 | 
	
		
			
				|  |  | -                        + "; ConfigAttributes: " + attr.toString());
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | +            // Attempt authentication if not already authenticated, or user always wants reauthentication
 | 
	
		
			
				|  |  | +            Authentication authenticated;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                // We check for just the property we're interested in (we do
 | 
	
		
			
				|  |  | -                // not call Context.validate() like the ContextInterceptor)
 | 
	
		
			
				|  |  | -                if (SecurityContextHolder.getContext().getAuthentication() == null) {
 | 
	
		
			
				|  |  | -                    credentialsNotFound(messages.getMessage(
 | 
	
		
			
				|  |  | -                            "AbstractSecurityInterceptor.authenticationNotFound",
 | 
	
		
			
				|  |  | -                            "An Authentication object was not found in the SecurityContext"),
 | 
	
		
			
				|  |  | -                        object, attr);
 | 
	
		
			
				|  |  | +            if (!SecurityContextHolder.getContext().getAuthentication()
 | 
	
		
			
				|  |  | +                                      .isAuthenticated()
 | 
	
		
			
				|  |  | +                || alwaysReauthenticate) {
 | 
	
		
			
				|  |  | +                try {
 | 
	
		
			
				|  |  | +                    authenticated = this.authenticationManager.authenticate(SecurityContextHolder.getContext()
 | 
	
		
			
				|  |  | +                                                                                                 .getAuthentication());
 | 
	
		
			
				|  |  | +                } catch (AuthenticationException authenticationException) {
 | 
	
		
			
				|  |  | +                    throw authenticationException;
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                // Attempt authentication if not already authenticated, or user always wants reauthentication
 | 
	
		
			
				|  |  | -                Authentication authenticated;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                if (!SecurityContextHolder.getContext().getAuthentication()
 | 
	
		
			
				|  |  | -                                          .isAuthenticated()
 | 
	
		
			
				|  |  | -                    || alwaysReauthenticate) {
 | 
	
		
			
				|  |  | -                    try {
 | 
	
		
			
				|  |  | -                        authenticated = this.authenticationManager.authenticate(SecurityContextHolder.getContext()
 | 
	
		
			
				|  |  | -                                                                                                     .getAuthentication());
 | 
	
		
			
				|  |  | -                    } catch (AuthenticationException authenticationException) {
 | 
	
		
			
				|  |  | -                        throw authenticationException;
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                    // We don't authenticated.setAuthentication(true), because each provider should do that
 | 
	
		
			
				|  |  | -                    if (logger.isDebugEnabled()) {
 | 
	
		
			
				|  |  | -                        logger.debug("Successfully Authenticated: "
 | 
	
		
			
				|  |  | -                            + authenticated.toString());
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                    SecurityContextHolder.getContext()
 | 
	
		
			
				|  |  | -                                         .setAuthentication(authenticated);
 | 
	
		
			
				|  |  | -                } else {
 | 
	
		
			
				|  |  | -                    authenticated = SecurityContextHolder.getContext()
 | 
	
		
			
				|  |  | -                                                         .getAuthentication();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                    if (logger.isDebugEnabled()) {
 | 
	
		
			
				|  |  | -                        logger.debug("Previously Authenticated: "
 | 
	
		
			
				|  |  | -                            + authenticated.toString());
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | +                // We don't authenticated.setAuthentication(true), because each provider should do that
 | 
	
		
			
				|  |  | +                if (logger.isDebugEnabled()) {
 | 
	
		
			
				|  |  | +                    logger.debug("Successfully Authenticated: "
 | 
	
		
			
				|  |  | +                        + authenticated.toString());
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                // Attempt authorization
 | 
	
		
			
				|  |  | -                try {
 | 
	
		
			
				|  |  | -                    this.accessDecisionManager.decide(authenticated, object,
 | 
	
		
			
				|  |  | -                        attr);
 | 
	
		
			
				|  |  | -                } catch (AccessDeniedException accessDeniedException) {
 | 
	
		
			
				|  |  | -                    AuthorizationFailureEvent event = new AuthorizationFailureEvent(object,
 | 
	
		
			
				|  |  | -                            attr, authenticated, accessDeniedException);
 | 
	
		
			
				|  |  | -                    this.eventPublisher.publishEvent(event);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                    throw accessDeniedException;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | +                SecurityContextHolder.getContext()
 | 
	
		
			
				|  |  | +                                     .setAuthentication(authenticated);
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                authenticated = SecurityContextHolder.getContext()
 | 
	
		
			
				|  |  | +                                                     .getAuthentication();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  if (logger.isDebugEnabled()) {
 | 
	
		
			
				|  |  | -                    logger.debug("Authorization successful");
 | 
	
		
			
				|  |  | +                    logger.debug("Previously Authenticated: "
 | 
	
		
			
				|  |  | +                        + authenticated.toString());
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                AuthorizedEvent event = new AuthorizedEvent(object, attr,
 | 
	
		
			
				|  |  | -                        authenticated);
 | 
	
		
			
				|  |  | +            // Attempt authorization
 | 
	
		
			
				|  |  | +            try {
 | 
	
		
			
				|  |  | +                this.accessDecisionManager.decide(authenticated, object,
 | 
	
		
			
				|  |  | +                    attr);
 | 
	
		
			
				|  |  | +            } catch (AccessDeniedException accessDeniedException) {
 | 
	
		
			
				|  |  | +                AuthorizationFailureEvent event = new AuthorizationFailureEvent(object,
 | 
	
		
			
				|  |  | +                        attr, authenticated, accessDeniedException);
 | 
	
		
			
				|  |  |                  this.eventPublisher.publishEvent(event);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                // Attempt to run as a different user
 | 
	
		
			
				|  |  | -                Authentication runAs = this.runAsManager.buildRunAs(authenticated,
 | 
	
		
			
				|  |  | -                        object, attr);
 | 
	
		
			
				|  |  | +                throw accessDeniedException;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                if (runAs == null) {
 | 
	
		
			
				|  |  | -                    if (logger.isDebugEnabled()) {
 | 
	
		
			
				|  |  | -                        logger.debug(
 | 
	
		
			
				|  |  | -                            "RunAsManager did not change Authentication object");
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | +            if (logger.isDebugEnabled()) {
 | 
	
		
			
				|  |  | +                logger.debug("Authorization successful");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    return new InterceptorStatusToken(authenticated, false,
 | 
	
		
			
				|  |  | -                        attr, object); // no further work post-invocation
 | 
	
		
			
				|  |  | -                } else {
 | 
	
		
			
				|  |  | -                    if (logger.isDebugEnabled()) {
 | 
	
		
			
				|  |  | -                        logger.debug("Switching to RunAs Authentication: "
 | 
	
		
			
				|  |  | -                            + runAs.toString());
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | +            AuthorizedEvent event = new AuthorizedEvent(object, attr,
 | 
	
		
			
				|  |  | +                    authenticated);
 | 
	
		
			
				|  |  | +            this.eventPublisher.publishEvent(event);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    SecurityContextHolder.getContext().setAuthentication(runAs);
 | 
	
		
			
				|  |  | +            // Attempt to run as a different user
 | 
	
		
			
				|  |  | +            Authentication runAs = this.runAsManager.buildRunAs(authenticated,
 | 
	
		
			
				|  |  | +                    object, attr);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    return new InterceptorStatusToken(authenticated, true,
 | 
	
		
			
				|  |  | -                        attr, object); // revert to token.Authenticated post-invocation
 | 
	
		
			
				|  |  | +            if (runAs == null) {
 | 
	
		
			
				|  |  | +                if (logger.isDebugEnabled()) {
 | 
	
		
			
				|  |  | +                    logger.debug(
 | 
	
		
			
				|  |  | +                        "RunAsManager did not change Authentication object");
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                return new InterceptorStatusToken(authenticated, false,
 | 
	
		
			
				|  |  | +                    attr, object); // no further work post-invocation
 | 
	
		
			
				|  |  |              } else {
 | 
	
		
			
				|  |  |                  if (logger.isDebugEnabled()) {
 | 
	
		
			
				|  |  | -                    logger.debug("Public object - authentication not attempted");
 | 
	
		
			
				|  |  | +                    logger.debug("Switching to RunAs Authentication: "
 | 
	
		
			
				|  |  | +                        + runAs.toString());
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                this.eventPublisher.publishEvent(new PublicInvocationEvent(
 | 
	
		
			
				|  |  | -                        object));
 | 
	
		
			
				|  |  | +                SecurityContextHolder.getContext().setAuthentication(runAs);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                return null; // no further work post-invocation
 | 
	
		
			
				|  |  | +                return new InterceptorStatusToken(authenticated, true,
 | 
	
		
			
				|  |  | +                    attr, object); // revert to token.Authenticated post-invocation
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +            if (logger.isDebugEnabled()) {
 | 
	
		
			
				|  |  | +                logger.debug("Public object - authentication not attempted");
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        /**
 | 
	
		
			
				|  |  | -         * Helper method which generates an exception containing the passed
 | 
	
		
			
				|  |  | -         * reason, and publishes an event to the application context.
 | 
	
		
			
				|  |  | -         * 
 | 
	
		
			
				|  |  | -         * <p>
 | 
	
		
			
				|  |  | -         * Always throws an exception.
 | 
	
		
			
				|  |  | -         * </p>
 | 
	
		
			
				|  |  | -         *
 | 
	
		
			
				|  |  | -         * @param reason to be provided in the exception detail
 | 
	
		
			
				|  |  | -         * @param secureObject that was being called
 | 
	
		
			
				|  |  | -         * @param configAttribs that were defined for the secureObject
 | 
	
		
			
				|  |  | -         */
 | 
	
		
			
				|  |  | -        private void credentialsNotFound(String reason, Object secureObject,
 | 
	
		
			
				|  |  | -            ConfigAttributeDefinition configAttribs) {
 | 
	
		
			
				|  |  | -            AuthenticationCredentialsNotFoundException exception = new AuthenticationCredentialsNotFoundException(reason);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            AuthenticationCredentialsNotFoundEvent event = new AuthenticationCredentialsNotFoundEvent(secureObject,
 | 
	
		
			
				|  |  | -                    configAttribs, exception);
 | 
	
		
			
				|  |  | -            this.eventPublisher.publishEvent(event);
 | 
	
		
			
				|  |  | +            this.eventPublisher.publishEvent(new PublicInvocationEvent(
 | 
	
		
			
				|  |  | +                    object));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            throw exception;
 | 
	
		
			
				|  |  | +            return null; // no further work post-invocation
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public AccessDecisionManager getAccessDecisionManager() {
 | 
	
		
			
				|  |  | -            return accessDecisionManager;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * Helper method which generates an exception containing the passed
 | 
	
		
			
				|  |  | +     * reason, and publishes an event to the application context.
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * <p>
 | 
	
		
			
				|  |  | +     * Always throws an exception.
 | 
	
		
			
				|  |  | +     * </p>
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param reason to be provided in the exception detail
 | 
	
		
			
				|  |  | +     * @param secureObject that was being called
 | 
	
		
			
				|  |  | +     * @param configAttribs that were defined for the secureObject
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private void credentialsNotFound(String reason, Object secureObject,
 | 
	
		
			
				|  |  | +        ConfigAttributeDefinition configAttribs) {
 | 
	
		
			
				|  |  | +        AuthenticationCredentialsNotFoundException exception = new AuthenticationCredentialsNotFoundException(reason);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public AfterInvocationManager getAfterInvocationManager() {
 | 
	
		
			
				|  |  | -            return afterInvocationManager;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        AuthenticationCredentialsNotFoundEvent event = new AuthenticationCredentialsNotFoundEvent(secureObject,
 | 
	
		
			
				|  |  | +                configAttribs, exception);
 | 
	
		
			
				|  |  | +        this.eventPublisher.publishEvent(event);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public AuthenticationManager getAuthenticationManager() {
 | 
	
		
			
				|  |  | -            return this.authenticationManager;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        throw exception;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public RunAsManager getRunAsManager() {
 | 
	
		
			
				|  |  | -            return runAsManager;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public AccessDecisionManager getAccessDecisionManager() {
 | 
	
		
			
				|  |  | +        return accessDecisionManager;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        /**
 | 
	
		
			
				|  |  | -         * Indicates the type of secure objects the subclass will be presenting
 | 
	
		
			
				|  |  | -         * to the abstract parent for processing. This is used to ensure
 | 
	
		
			
				|  |  | -         * collaborators wired to the <code>AbstractSecurityInterceptor</code>
 | 
	
		
			
				|  |  | -         * all support the indicated secure object class.
 | 
	
		
			
				|  |  | -         *
 | 
	
		
			
				|  |  | -         * @return the type of secure object the subclass provides services for
 | 
	
		
			
				|  |  | -         */
 | 
	
		
			
				|  |  | -        public abstract Class getSecureObjectClass();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        public boolean isAlwaysReauthenticate() {
 | 
	
		
			
				|  |  | -            return alwaysReauthenticate;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public AfterInvocationManager getAfterInvocationManager() {
 | 
	
		
			
				|  |  | +        return afterInvocationManager;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public boolean isRejectPublicInvocations() {
 | 
	
		
			
				|  |  | -            return rejectPublicInvocations;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public AuthenticationManager getAuthenticationManager() {
 | 
	
		
			
				|  |  | +        return this.authenticationManager;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public boolean isValidateConfigAttributes() {
 | 
	
		
			
				|  |  | -            return validateConfigAttributes;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public RunAsManager getRunAsManager() {
 | 
	
		
			
				|  |  | +        return runAsManager;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public abstract ObjectDefinitionSource obtainObjectDefinitionSource();
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * Indicates the type of secure objects the subclass will be presenting
 | 
	
		
			
				|  |  | +     * to the abstract parent for processing. This is used to ensure
 | 
	
		
			
				|  |  | +     * collaborators wired to the <code>AbstractSecurityInterceptor</code>
 | 
	
		
			
				|  |  | +     * all support the indicated secure object class.
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @return the type of secure object the subclass provides services for
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public abstract Class getSecureObjectClass();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public void setAccessDecisionManager(
 | 
	
		
			
				|  |  | -            AccessDecisionManager accessDecisionManager) {
 | 
	
		
			
				|  |  | -            this.accessDecisionManager = accessDecisionManager;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public boolean isAlwaysReauthenticate() {
 | 
	
		
			
				|  |  | +        return alwaysReauthenticate;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public void setAfterInvocationManager(
 | 
	
		
			
				|  |  | -            AfterInvocationManager afterInvocationManager) {
 | 
	
		
			
				|  |  | -            this.afterInvocationManager = afterInvocationManager;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public boolean isRejectPublicInvocations() {
 | 
	
		
			
				|  |  | +        return rejectPublicInvocations;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        /**
 | 
	
		
			
				|  |  | -         * Indicates whether the <code>AbstractSecurityInterceptor</code>
 | 
	
		
			
				|  |  | -         * should ignore the {@link Authentication#isAuthenticated()}
 | 
	
		
			
				|  |  | -         * property. Defaults to <code>false</code>, meaning by default the
 | 
	
		
			
				|  |  | -         * <code>Authentication.isAuthenticated()</code> property is trusted
 | 
	
		
			
				|  |  | -         * and re-authentication will not occur if the principal has already
 | 
	
		
			
				|  |  | -         * been authenticated.
 | 
	
		
			
				|  |  | -         *
 | 
	
		
			
				|  |  | -         * @param alwaysReauthenticate <code>true</code> to force
 | 
	
		
			
				|  |  | -         *        <code>AbstractSecurityInterceptor</code> to disregard the
 | 
	
		
			
				|  |  | -         *        value of <code>Authentication.isAuthenticated()</code> and
 | 
	
		
			
				|  |  | -         *        always re-authenticate the request (defaults to
 | 
	
		
			
				|  |  | -         *        <code>false</code>).
 | 
	
		
			
				|  |  | -         */
 | 
	
		
			
				|  |  | -        public void setAlwaysReauthenticate(boolean alwaysReauthenticate) {
 | 
	
		
			
				|  |  | -            this.alwaysReauthenticate = alwaysReauthenticate;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public boolean isValidateConfigAttributes() {
 | 
	
		
			
				|  |  | +        return validateConfigAttributes;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public void setApplicationEventPublisher(
 | 
	
		
			
				|  |  | -            ApplicationEventPublisher eventPublisher) {
 | 
	
		
			
				|  |  | -            this.eventPublisher = eventPublisher;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public abstract ObjectDefinitionSource obtainObjectDefinitionSource();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public void setAuthenticationManager(AuthenticationManager newManager) {
 | 
	
		
			
				|  |  | -            this.authenticationManager = newManager;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public void setAccessDecisionManager(
 | 
	
		
			
				|  |  | +        AccessDecisionManager accessDecisionManager) {
 | 
	
		
			
				|  |  | +        this.accessDecisionManager = accessDecisionManager;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public void setMessageSource(MessageSource messageSource) {
 | 
	
		
			
				|  |  | -            this.messages = new MessageSourceAccessor(messageSource);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public void setAfterInvocationManager(
 | 
	
		
			
				|  |  | +        AfterInvocationManager afterInvocationManager) {
 | 
	
		
			
				|  |  | +        this.afterInvocationManager = afterInvocationManager;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        /**
 | 
	
		
			
				|  |  | -         * By rejecting public invocations (and setting this property to
 | 
	
		
			
				|  |  | -         * <code>true</code>), essentially you are ensuring that every secure
 | 
	
		
			
				|  |  | -         * object invocation advised by
 | 
	
		
			
				|  |  | -         * <code>AbstractSecurityInterceptor</code> has a configuration
 | 
	
		
			
				|  |  | -         * attribute defined. This is useful to ensure a "fail safe" mode
 | 
	
		
			
				|  |  | -         * where undeclared secure objects will be rejected and configuration
 | 
	
		
			
				|  |  | -         * omissions detected early. An <code>IllegalArgumentException</code>
 | 
	
		
			
				|  |  | -         * will be thrown by the <code>AbstractSecurityInterceptor</code> if
 | 
	
		
			
				|  |  | -         * you set this property to <code>true</code> and an attempt is made
 | 
	
		
			
				|  |  | -         * to invoke a secure object that has no configuration attributes.
 | 
	
		
			
				|  |  | -         *
 | 
	
		
			
				|  |  | -         * @param rejectPublicInvocations set to <code>true</code> to reject
 | 
	
		
			
				|  |  | -         *        invocations of secure objects that have no configuration
 | 
	
		
			
				|  |  | -         *        attributes (by default it is <code>true</code> which treats
 | 
	
		
			
				|  |  | -         *        undeclared secure objects as "public" or unauthorized)
 | 
	
		
			
				|  |  | -         */
 | 
	
		
			
				|  |  | -        public void setRejectPublicInvocations(boolean rejectPublicInvocations) {
 | 
	
		
			
				|  |  | -            this.rejectPublicInvocations = rejectPublicInvocations;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * Indicates whether the <code>AbstractSecurityInterceptor</code>
 | 
	
		
			
				|  |  | +     * should ignore the {@link Authentication#isAuthenticated()}
 | 
	
		
			
				|  |  | +     * property. Defaults to <code>false</code>, meaning by default the
 | 
	
		
			
				|  |  | +     * <code>Authentication.isAuthenticated()</code> property is trusted
 | 
	
		
			
				|  |  | +     * and re-authentication will not occur if the principal has already
 | 
	
		
			
				|  |  | +     * been authenticated.
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param alwaysReauthenticate <code>true</code> to force
 | 
	
		
			
				|  |  | +     *        <code>AbstractSecurityInterceptor</code> to disregard the
 | 
	
		
			
				|  |  | +     *        value of <code>Authentication.isAuthenticated()</code> and
 | 
	
		
			
				|  |  | +     *        always re-authenticate the request (defaults to
 | 
	
		
			
				|  |  | +     *        <code>false</code>).
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public void setAlwaysReauthenticate(boolean alwaysReauthenticate) {
 | 
	
		
			
				|  |  | +        this.alwaysReauthenticate = alwaysReauthenticate;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public void setRunAsManager(RunAsManager runAsManager) {
 | 
	
		
			
				|  |  | -            this.runAsManager = runAsManager;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public void setApplicationEventPublisher(
 | 
	
		
			
				|  |  | +        ApplicationEventPublisher eventPublisher) {
 | 
	
		
			
				|  |  | +        this.eventPublisher = eventPublisher;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public void setValidateConfigAttributes(
 | 
	
		
			
				|  |  | -            boolean validateConfigAttributes) {
 | 
	
		
			
				|  |  | -            this.validateConfigAttributes = validateConfigAttributes;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    public void setAuthenticationManager(AuthenticationManager newManager) {
 | 
	
		
			
				|  |  | +        this.authenticationManager = newManager;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void setMessageSource(MessageSource messageSource) {
 | 
	
		
			
				|  |  | +        this.messages = new MessageSourceAccessor(messageSource);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * By rejecting public invocations (and setting this property to
 | 
	
		
			
				|  |  | +     * <code>true</code>), essentially you are ensuring that every secure
 | 
	
		
			
				|  |  | +     * object invocation advised by
 | 
	
		
			
				|  |  | +     * <code>AbstractSecurityInterceptor</code> has a configuration
 | 
	
		
			
				|  |  | +     * attribute defined. This is useful to ensure a "fail safe" mode
 | 
	
		
			
				|  |  | +     * where undeclared secure objects will be rejected and configuration
 | 
	
		
			
				|  |  | +     * omissions detected early. An <code>IllegalArgumentException</code>
 | 
	
		
			
				|  |  | +     * will be thrown by the <code>AbstractSecurityInterceptor</code> if
 | 
	
		
			
				|  |  | +     * you set this property to <code>true</code> and an attempt is made
 | 
	
		
			
				|  |  | +     * to invoke a secure object that has no configuration attributes.
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param rejectPublicInvocations set to <code>true</code> to reject
 | 
	
		
			
				|  |  | +     *        invocations of secure objects that have no configuration
 | 
	
		
			
				|  |  | +     *        attributes (by default it is <code>true</code> which treats
 | 
	
		
			
				|  |  | +     *        undeclared secure objects as "public" or unauthorized)
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public void setRejectPublicInvocations(boolean rejectPublicInvocations) {
 | 
	
		
			
				|  |  | +        this.rejectPublicInvocations = rejectPublicInvocations;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void setRunAsManager(RunAsManager runAsManager) {
 | 
	
		
			
				|  |  | +        this.runAsManager = runAsManager;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void setValidateConfigAttributes(
 | 
	
		
			
				|  |  | +        boolean validateConfigAttributes) {
 | 
	
		
			
				|  |  | +        this.validateConfigAttributes = validateConfigAttributes;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +}
 |