Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security authentication manager won't get picked up on custom filter

I'm trying to create a custom filter to take care of authentication, since I'm forced to use a combination of an AD and local database (arg!) to determine access rights. I'm using the official docs, for this particular issue mostly this part.

However, when I run my server it is complaining about the AuthenticationManager being null, while I believe I am setting it in XML as covered in this SO question. What am I missing here?

The exception:

SEVERE: Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myUsernamePasswordAuthenticationFilter' defined in file [*snip*]:
Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: authenticationManager must be specified
...
Caused by: java.lang.IllegalArgumentException: authenticationManager must be specified
at org.springframework.util.Assert.notNull(Assert.java:112)

The XML: (with some simplified class names)

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:sec="http://www.springframework.org/schema/security"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.2.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.1.xsd">

<context:property-placeholder location="classpath*:META-INF/spring/*.properties" />
<context:spring-configured />
<context:component-scan base-package="myapp" />

<!-- Spring Security Configuration. -->
<sec:http auto-config="false" entry-point-ref="loginUrlAuthenticationEntryPoint"
        access-denied-page="/denied.jsp">
    <sec:custom-filter position="FORM_LOGIN_FILTER" ref="myAuthenticationFilter" />

    <sec:intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <sec:intercept-url pattern="/404.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <sec:intercept-url pattern="/index.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <sec:intercept-url pattern="/**" access="ROLE_USER" />

    <sec:logout logout-url="/logout" logout-success-url="/login" />
</sec:http>
<sec:authentication-manager alias="authenticationManager">
    <sec:authentication-provider ref="myAuthenticationProvider" />
</sec:authentication-manager>

<bean id="loginUrlAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    <property name="loginFormUrl" value="/login" />
</bean>
<bean id="myAuthenticationFilter" class="myapp.MyUsernamePasswordAuthenticationFilter">
    <property name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="myAuthenticationProvider" class="myapp.MyAuthenticationProvider" />

The Filter:

@Component
public class MyUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public AdminUsernamePasswordAuthenticationFilter() {
    super("/login");
}

@Override
public Authentication attemptAuthentication(final HttpServletRequest request,
        final HttpServletResponse response) throws AuthenticationException {
    // stuff and:
    return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(
            login, request.getParameter("password")));
}
}

The AuthenticationProvider:

@Component
public class MyAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
    // all the funky AD+DB code
    return null;
}

@Override
public boolean supports(final Class<?> clazz) {
    return true;
}
}

I am running Java 6, the latest Spring Security (3.1.4.RELEASE) and Spring (3.2.3.RELEASE) versions, running on a Tomcat v6 server. Different Spring versions do not appear to be a problem (related SO question). And if it would be a problem, having to run Spring 3.1.4 if you want to use Spring Security is just meh...

Some additional things I tried to no avail:

  1. I tried ditching the <sec:authentication-manager /> in favour of a normal bean, as mentioned here (bottom answer).
  2. I tried adding bean id's, names, authentication-manager-refs in all sorts of combinations.
like image 694
basvanstratum Avatar asked Dec 27 '22 01:12

basvanstratum


1 Answers

Ah... I spot the basic error made by many in Spring. You have your bean MyUsernamePasswordAuthenticationFilter defined in XML, which is correct. However you have it also annotated by @Component annotation, which means it is being picked and registered as another bean definition by component scan. And bean instance comming from this definition won't indeed have its authenticationManager dependency initalized.

Just remove the @Component annotation in MyUsernamePasswordAuthenticationFilter and you should be OK.

like image 160
Pavel Horal Avatar answered Jan 15 '23 13:01

Pavel Horal