Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot Autowire UserDetailsService into WebSecurityConfigurerAdapter

Hi I have a problem with Autowired UsrDetailsService, I found that many others have the same problem but no other solution works for me (and I dont know why) I use java configuration (no xml)

Error code
 org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'securityConfig':
Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private com.mycompany.delivery.service.AccountServiceImpl com.mycompany.delivery.config.SecurityConfig.accUserDetailsService;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type [com.mycompany.delivery.service.AccountServiceImpl] found for dependency: 
expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: 
{@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=accUserDetailsService)}

When I Autowired this class to Controller, or anywhere else it works fine, everything else is autowiring fine as well only to WebSecurityConfigurerAdapter I cant.

My Security config:

Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {



    @Autowired
    @Qualifier("accUserDetailsService")
    private AccountServiceImpl accUserDetailsService;

    public AccountServiceImpl getAccUserDetailsService() {
        return accUserDetailsService;
    }

    public void setAccUserDetailsService(AccountServiceImpl accUserDetailsService) {
        this.accUserDetailsService = accUserDetailsService;
    }

   // @Override
    // protected void configure(AuthenticationManagerBuilder registry) throws Exception {
    //     registry.userDetailsService(accUserDetailsService);
    //}
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("mkyong").password("123456").roles("USER");
        auth.inMemoryAuthentication().withUser("admin").password("123456").roles("ADMIN");
        auth.inMemoryAuthentication().withUser("dba").password("123456").roles("DBA");
    }

    //.csrf() is optional, enabled by default, if using WebSecurityConfigurerAdapter constructor
    @Bean(name = "myAuthenticationManager")
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/admin/**").access("hasRole('ROLE_USER')")
                .antMatchers("/admin/partlyVisible/**").access("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')").and()
                .formLogin().loginPage("/admin/login").failureUrl("/admin/login?error")
                .usernameParameter("username").passwordParameter("password")
                .and()
                .logout().logoutSuccessUrl("/admin/login?logout").and()
                .exceptionHandling().accessDeniedPage("/admin/403")
                .and()
                .csrf();
    }
}

My WebMvcConfigurerAdapter

@Configuration
@EnableWebMvc
@Import({ SecurityConfig.class })
@ComponentScan(basePackages = "com.mycompany.*")
@ImportResource({"classpath:applicationContext.xml"})
@EnableTransactionManagement
public class MySpringMvcConfig extends WebMvcConfigurerAdapter {

    final static Logger log = LoggerFactory.getLogger(MySpringMvcConfig.class);

    /**
     * Maps the main page to a specific view.
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        log.debug("mapping URL / to home view");
        registry.addViewController("/").setViewName("home");
        registry.addViewController("/snoop").setViewName("snoop");
    }


    /**
     * Enables default Tomcat servlet that serves static files.
     */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        log.debug("enabling default servlet for static files");
        configurer.enable();
    }

    /**
     * Provides mapping from view names to JSP pages in WEB-INF/jsp directory.
     */
    @Bean
    public ViewResolver viewResolver() {
        log.debug("registering JSP in /WEB-INF/jsp/ as views");
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/jsp/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }

    /**
     * Provides localized messages.
     */
    @Bean
    public MessageSource messageSource() {
        log.debug("registering ResourceBundle 'Texts' for messages");
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("Texts");
        return messageSource;
    }

    /**
     * Provides JSR-303 Validator.
     */
    @Bean
    public Validator validator() {
        log.debug("validator()");
        return new LocalValidatorFactoryBean();
    }

}

AbstractAnnotationConfigDispatcherServletInitializer

public class MyStartInitializer extends AbstractAnnotationConfigDispatcherServletInitializer  {

    private Object sc;

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        //create Spring beans context configured in MySpringMvcConfig.class
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(MySpringMvcConfig.class);
        ctx.register(SecurityConfig.class);

        //register Spring MVC main Dispatcher servlet
        ServletRegistration.Dynamic disp = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
        disp.setLoadOnStartup(1);
        disp.addMapping("/");



        //register filter setting utf-8 encoding on all requests
        FilterRegistration.Dynamic encoding = servletContext.addFilter("encoding", CharacterEncodingFilter.class);
        encoding.setInitParameter("encoding", "utf-8");
        encoding.addMappingForUrlPatterns(null, false, "/*");

        //register bundle also for JSTL fmt: tags which are not behind DispatcherServlet
        servletContext.setInitParameter(Config.FMT_LOCALIZATION_CONTEXT, "Texts");

    }

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { MySpringMvcConfig.class, SecurityConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
      return null;
    }

    @Override
    protected String[] getServletMappings() {
       return new String[] { "/" };
    }
}

AbstractSecurityWebApplicationInitializer

public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {

   public SpringSecurityInitializer() {
        super(SecurityConfig.class);
    }
}

And last my UserDetailsService

@Service(value = "accUserDetailsService")
public class AccountServiceImpl implements UserDetailsService {


    @Autowired
    private AccountDAO accountDao;

    public AccountDAO getAccountDao() {
        return accountDao;
    }

    public void setAccountDao(AccountDAO accountDao) {
        this.accountDao = accountDao;
    }

    @Override
    public UserDetails loadUserByUsername(String string) throws UsernameNotFoundException {
        UserDetails userDetails = null;
        Account account = accountDao.getByLogin(string);

        if (account == null) {
            throw new UsernameNotFoundException("Account not found.");
        }

        userDetails = new AccountAdapter(account);
        return userDetails;
    }


}

Thanks for helping

like image 267
kronas Avatar asked Nov 09 '22 20:11

kronas


1 Answers

After another hour i made it work (but not sure how/why)

My Security config:

@Configuration
@EnableWebSecurity

change to

@Configuration
@EnableWebMvcSecurity
@ImportResource({"classpath:applicationContext.xml"})
@EnableGlobalMethodSecurity

where ImportResource is important, but now i have importrecource twice, first time here second time in WebMvcConfigurerAdapter

like image 105
kronas Avatar answered Nov 15 '22 10:11

kronas