Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How To Inject AuthenticationManager using Java Configuration in a Custom Filter

I'm using Spring Security 3.2 and Spring 4.0.1

I'm working on converting an xml config into a Java config. When I annotate AuthenticationManager with @Autowired in my Filter, I'm getting an exception

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.authentication.AuthenticationManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {} 

I've tried injecting AuthenticationManagerFactoryBean but that also fails with a similar exception.

Here is the XML configuration I'm working from

<?xml version="1.0" encoding="UTF-8"?> <beans ...>     <security:authentication-manager id="authenticationManager">         <security:authentication-provider user-service-ref="userDao">             <security:password-encoder ref="passwordEncoder"/>         </security:authentication-provider>     </security:authentication-manager>      <security:http             realm="Protected API"             use-expressions="true"             auto-config="false"             create-session="stateless"             entry-point-ref="unauthorizedEntryPoint"             authentication-manager-ref="authenticationManager">         <security:access-denied-handler ref="accessDeniedHandler"/>         <security:custom-filter ref="tokenAuthenticationProcessingFilter" position="FORM_LOGIN_FILTER"/>         <security:custom-filter ref="tokenFilter" position="REMEMBER_ME_FILTER"/>         <security:intercept-url method="GET" pattern="/rest/news/**" access="hasRole('user')"/>         <security:intercept-url method="PUT" pattern="/rest/news/**" access="hasRole('admin')"/>         <security:intercept-url method="POST" pattern="/rest/news/**" access="hasRole('admin')"/>         <security:intercept-url method="DELETE" pattern="/rest/news/**" access="hasRole('admin')"/>     </security:http>      <bean class="com.unsubcentral.security.TokenAuthenticationProcessingFilter"           id="tokenAuthenticationProcessingFilter">         <constructor-arg value="/rest/user/authenticate"/>         <property name="authenticationManager" ref="authenticationManager"/>         <property name="authenticationSuccessHandler" ref="authenticationSuccessHandler"/>         <property name="authenticationFailureHandler" ref="authenticationFailureHandler"/>     </bean>  </beans> 

Here is the Java Config I'm attempting

@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter {      @Autowired     private UserDetailsService userDetailsService;      @Autowired     private PasswordEncoder passwordEncoder;      @Autowired     private AuthenticationEntryPoint authenticationEntryPoint;      @Autowired     private AccessDeniedHandler accessDeniedHandler;      @Override     protected void configure(AuthenticationManagerBuilder auth) throws Exception {         auth                 .userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);     }      @Override     protected void configure(HttpSecurity http) throws Exception {         http                 .sessionManagement()                     .sessionCreationPolicy(SessionCreationPolicy.STATELESS)                     .and()                 .exceptionHandling()                     .authenticationEntryPoint(authenticationEntryPoint)                     .accessDeniedHandler(accessDeniedHandler)                     .and();         //TODO: Custom Filters     } } 

And this is the Custom Filter class. The line giving me trouble is the setter for AuthenticationManager

@Component public class TokenAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {       @Autowired     public TokenAuthenticationProcessingFilter(@Value("/rest/useAuthenticationManagerr/authenticate") String defaultFilterProcessesUrl) {         super(defaultFilterProcessesUrl);     }       @Override     public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {       ...     }      private String obtainPassword(HttpServletRequest request) {         return request.getParameter("password");     }      private String obtainUsername(HttpServletRequest request) {         return request.getParameter("username");     }      @Autowired     @Override     public void setAuthenticationManager(AuthenticationManager authenticationManager) {         super.setAuthenticationManager(authenticationManager);     }      @Autowired     @Override     public void setAuthenticationSuccessHandler(AuthenticationSuccessHandler successHandler) {         super.setAuthenticationSuccessHandler(successHandler);     }      @Autowired     @Override     public void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) {         super.setAuthenticationFailureHandler(failureHandler);     } } 
like image 643
rince Avatar asked Feb 07 '14 16:02

rince


Video Answer


2 Answers

Override method authenticationManagerBean in WebSecurityConfigurerAdapter to expose the AuthenticationManager built using configure(AuthenticationManagerBuilder) as a Spring bean:

For example:

   @Bean(name = BeanIds.AUTHENTICATION_MANAGER)    @Override    public AuthenticationManager authenticationManagerBean() throws Exception {        return super.authenticationManagerBean();    } 
like image 65
Angular University Avatar answered Sep 21 '22 09:09

Angular University


In addition to what Angular University said above you may want to use @Import to aggregate @Configuration classes to the other class (AuthenticationController in my case) :

@Import(SecurityConfig.class) @RestController public class AuthenticationController { @Autowired private AuthenticationManager authenticationManager; //some logic } 

Spring doc about Aggregating @Configuration classes with @Import: link

like image 27
AbdEllah Abril Avatar answered Sep 20 '22 09:09

AbdEllah Abril