diff --git a/core/src/main/java/org/acegisecurity/intercept/AbstractSecurityInterceptor.java b/core/src/main/java/org/acegisecurity/intercept/AbstractSecurityInterceptor.java index 80dcd620d9..9b34a5f824 100644 --- a/core/src/main/java/org/acegisecurity/intercept/AbstractSecurityInterceptor.java +++ b/core/src/main/java/org/acegisecurity/intercept/AbstractSecurityInterceptor.java @@ -132,6 +132,9 @@ import org.springframework.util.Assert; * * *
+ * + * @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. - * - *- * Always throws an exception. - *
- * - * @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. + * + *+ * Always throws an exception. + *
+ * + * @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 theAbstractSecurityInterceptor
- * 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 AbstractSecurityInterceptor
+ * 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 AbstractSecurityInterceptor
- * should ignore the {@link Authentication#isAuthenticated()}
- * property. Defaults to false, meaning by default the
- * Authentication.isAuthenticated() property is trusted
- * and re-authentication will not occur if the principal has already
- * been authenticated.
- *
- * @param alwaysReauthenticate true to force
- * AbstractSecurityInterceptor to disregard the
- * value of Authentication.isAuthenticated() and
- * always re-authenticate the request (defaults to
- * false).
- */
- 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
- * true), essentially you are ensuring that every secure
- * object invocation advised by
- * AbstractSecurityInterceptor 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 IllegalArgumentException
- * will be thrown by the AbstractSecurityInterceptor if
- * you set this property to true and an attempt is made
- * to invoke a secure object that has no configuration attributes.
- *
- * @param rejectPublicInvocations set to true to reject
- * invocations of secure objects that have no configuration
- * attributes (by default it is true which treats
- * undeclared secure objects as "public" or unauthorized)
- */
- public void setRejectPublicInvocations(boolean rejectPublicInvocations) {
- this.rejectPublicInvocations = rejectPublicInvocations;
- }
+ /**
+ * Indicates whether the AbstractSecurityInterceptor
+ * should ignore the {@link Authentication#isAuthenticated()}
+ * property. Defaults to false, meaning by default the
+ * Authentication.isAuthenticated() property is trusted
+ * and re-authentication will not occur if the principal has already
+ * been authenticated.
+ *
+ * @param alwaysReauthenticate true to force
+ * AbstractSecurityInterceptor to disregard the
+ * value of Authentication.isAuthenticated() and
+ * always re-authenticate the request (defaults to
+ * false).
+ */
+ 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
+ * true), essentially you are ensuring that every secure
+ * object invocation advised by
+ * AbstractSecurityInterceptor 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 IllegalArgumentException
+ * will be thrown by the AbstractSecurityInterceptor if
+ * you set this property to true and an attempt is made
+ * to invoke a secure object that has no configuration attributes.
+ *
+ * @param rejectPublicInvocations set to true to reject
+ * invocations of secure objects that have no configuration
+ * attributes (by default it is true 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;
}
+}