11

We have Spring MVC application. We are trying to integrate the Spring security in it.

We have written our custom authentication provider which will do the work of authentication.

Below is the code for my custom authentication provider.

    public class CustomAuthenticationProvider extends DaoAuthenticationProvider {

    @Autowired
    private AuthenticationService authenticationService;

    @Override
    public Authentication authenticate(Authentication authentication) {

        CustomAuthenticationToken auth = (CustomAuthenticationToken) authentication;

        String username = String.valueOf(auth.getPrincipal());
        String password = String.valueOf(auth.getCredentials());

        try {

            Users user = new User();
            user.setUsername(username);
            user.setPassword(PasswordUtil.encrypt(password));

            user = authenticationService.validateLogin(user);

            return auth;
        } catch (Exception e) {
            throw new BadCredentialsException("Username/Password does not match for " + username);
        }
    }

    @Override
    public boolean supports(Class<? extends Object> authentication) {
        return (CustomAuthenticationToken.class.isAssignableFrom(authentication));

    }
}

Here i am getting NullpointerException on the following line

user = authenticationService.validateLogin(user);

The authenticationService is not getting autowired in the custom authentication provider. While the same service authenticationService is autowired in the same way in my MVC controller.

Is this because authentication provider is a Spring security component?

Below is a my web.xml

    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/spring/myApp-security.xml
    </param-value>
</context-param>

<servlet>
    <servlet-name>myApp</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/myApp-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>myApp</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Edit 1 :-

I have added the following lines in my spring security configuration file.

<beans:bean id="customAuthenticationProvider" class="com.myApp.security.provider.CustomAuthenticationProvider">
    <beans:property name="userDetailsService" ref="userDetailsService"/>   
</beans:bean>

Please help how to autowire my service classes in the Spring security components?

ajm
  • 12,863
  • 58
  • 163
  • 234

7 Answers7

4

Are you using the <debug/> element? If so, try removing to see if it fixes your problem as SEC-1885 prevents @Autowired from working when using <debug/>.

Rob Winch
  • 21,440
  • 2
  • 59
  • 76
  • gooood !!! I spent 4 hours to figure out why it was not working, and even created this post http://stackoverflow.com/questions/23437738/autowiring-does-not-work-spring-security-on-appengine-authentication-handler. thanks, Rob!! that was the problem in my case.(i still work with 3.1.0) – OhadR May 02 '14 at 22:21
3

I experienced this issue and came to the conclusion that while autowiring was taking place, the spring security was operating with a completely different instance of the classes. To solve this I imported the security configuration into the spring mvc configuration as below.

This allowed Spring security to share the context with my spring mvc.

<import resource="myapp-security.xml" />
antyrat
  • 27,479
  • 9
  • 75
  • 76
LeeJ
  • 31
  • 3
3

Perhaps autowiring postprocessor is not enabled in the root application context (but enabled in the DispatcherServlet's context as a side effect of <mvc:annotation-driven> or <context:component-scan>).

You can enable it by adding <context:annotation-config> to myApp-security.xml.

axtavt
  • 239,438
  • 41
  • 511
  • 482
1

I faced the same issue and fixed it.

The solution is even if u have @Autowired annotation set for Service class.

 @Autowired
 private AuthenticationService authenticationService;

Removed the bean definition in your dispatcher-servlet.xml and it will work.

 <!--
 <beans:bean id="customAuthenticationProvider" class="com.myApp.security.provider.CustomAuthenticationProvider">
 <beans:property name="userDetailsService" ref="userDetailsService"/>   
 </beans:bean>
 -->

and add it in security context file

Giridhar
  • 512
  • 5
  • 20
1

if you are using Spring MVC then you have to add both spring-security.xml and dispatcher-servlet.xml in contextConfigLocation.

<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring-security.xml
            /WEB-INF/dispatcher-servlet.xml
        </param-value>
    </context-param>
SHIVA
  • 646
  • 1
  • 8
  • 13
0

You should use You cannot use because your myApp-security.xml is creating another ApplicationContext which doesnt see all the autowiring from your context created by myApp-servlet.xml

Alan Berezin
  • 533
  • 4
  • 13
0

you need to define your CustomAuthenticationProvider as a spring bean (in applicationContext.xml generally or applicationContext-security.xml if you have one)

Jerome Cance
  • 8,103
  • 12
  • 53
  • 106
  • C Thanks for the answer. I have defined my custom authentication provider in spring security xml. Please see I have updated my question. Do I need to do anything else? – ajm Aug 11 '11 at 10:05
  • I don't see your AuthenticationService in your bean config file. AuthenticationService must also be defined as a bean. Is your CustomAuthenticationProvider is also autowired where you try to use it ? Because if you instanciate it yourself, spring cannot wrap it in a proxy – Jerome Cance Aug 11 '11 at 10:12
  • AuthenticationService is not defined in the bean config file as I have used @Service annotation here. – ajm Aug 11 '11 at 10:31