Search code examples
authenticationspring-securitywebsphere-7

Spring Security Method Security Interceptor not picking up authenticationManager


I'm trying to write a custom method security interceptor. However, it isn't using the authentication manager I added to the bean properties in my security context and returning null when I check to see if the authentication manager exists. Could anyone shed light on why the authentication manager bean property isn't being used? I'm using spring security 3.0.5 on WebSphere 7.0

Here's the bean containing the method interceptor

<beans:bean id="methodInterceptor"
    class="bigbank.security.CustomMethodSecInterceptor">
    <beans:property name="authenticationManager" ref="authenticationManager" />
    <beans:property name="accessDecisionManager" ref="universalAccessDecisionManager" />
    <beans:property name="securityMetadataSource" ref="tspmMethodSecurityMetaData" />

Here's my method security interceptor

public class CustomMethodSecInterceptor extends MethodSecurityInterceptor {

private static final Log logger = LogFactory
        .getLog(WebSphere2SpringSecurityPropagationInterceptor.class);
private AuthenticationManager authenticationManager = null;
private AuthenticationDetailsSource authenticationDetailsSource = new WebSpherePreAuthenticatedAuthenticationDetailsSource();
private final WASUsernameAndGroupsExtractor wasHelper;

public CustomMethodSecInterceptor() {
    wasHelper = new DefaultWASUsernameAndGroupsExtractor();
}

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
    try {
        logger.debug("Performing Spring Security authentication with WebSphere credentials");
        System.out.println("@@going through ss authentication");
        authenticateSpringSecurityWithWASCredentials();
        InterceptorStatusToken token = super.beforeInvocation(mi);

        logger.debug("Proceeding with method invocation");
        Object result = mi.proceed();
        return super.afterInvocation(token, result);

    } finally {
        logger.debug("Clearing Spring Security security context");
        SecurityContextHolder.clearContext();
    }
}

private void authenticateSpringSecurityWithWASCredentials() {
    Assert.notNull(authenticationManager); // This is where the error is coming up
    Assert.notNull(authenticationDetailsSource);

    String userName = wasHelper.getCurrentUserName();
    if (logger.isDebugEnabled()) {
        logger.debug("Creating authentication request for user " + userName);
    }
    PreAuthenticatedAuthenticationToken authRequest = new PreAuthenticatedAuthenticationToken(
            userName, "N/A");
    authRequest.setDetails(authenticationDetailsSource.buildDetails(null));
    if (logger.isDebugEnabled()) {
        logger.debug("Authentication request for user " + userName + ": "
                + authRequest);
    }
    Authentication authResponse = authenticationManager
            .authenticate(authRequest);
    if (logger.isDebugEnabled()) {
        logger.debug("Authentication response for user " + userName + ": "
                + authResponse);
    }
    SecurityContextHolder.getContext().setAuthentication(authResponse);
}

public void setAuthenticationManager(
        AuthenticationManager authenticationManager) {
    this.authenticationManager = authenticationManager;
}

}

Here's the error:

Caused by: java.lang.IllegalArgumentException: An AuthenticationManager is required
at org.springframework.util.Assert.notNull(Assert.java:112)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.afterPropertiesSet(AbstractSecurityInterceptor.java:118)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1469)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1409)
... 119 more

Solution

  • You have overridden the setAuthenticationManager method, so when it is invoked by Spring to inject the AuthenticationManager, it doesn't set the corresponding field in AbstractSecurityInterceptor.

    Since the base class contains a getter for this property, you would be best to remove the field and setter method, and just use the getter to access the authentication manager in your code.