2016-02-20 5 views
3

Недавно я вернулся к проекту Spring, над которым я работал, и у меня возникли проблемы при запуске приложения. Этот вопрос, вероятно, является дубликатом, но я не смог найти ответ.Spring Security config autowiring custom UserDetailsService bean

Вот отрывок из моей первоначальной SecurityConfig.java:

объект
@Configuration 
@EnableWebSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired private UserService userService; 

    /** 
    * Global security config to set the user details service etc. 
    * @param auth authentication manager 
    * @throws Exception 
    */ 
    @Autowired 
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 
     auth 
       .userDetailsService(userService) 
       .passwordEncoder(passwordEncoder()); 
    } 

UserService реализует UserDetailsService. Это дало ошибку при запуске:

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.clubmate.web.service.UserService com.clubmate.web.config.SecurityConfig.userService; nested exception is java.lang.IllegalArgumentException: Can not set com.clubmate.web.service.UserService field com.clubmate.web.config.SecurityConfig.userService to com.sun.proxy.$Proxy62 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573) 
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) 
    ... 58 more 
Caused by: java.lang.IllegalArgumentException: Can not set com.clubmate.web.service.UserService field com.clubmate.web.config.SecurityConfig.userService to com.sun.proxy.$Proxy62 
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167) 
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171) 
    at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81) 
    at java.lang.reflect.Field.set(Field.java:764) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:569) 
    ... 60 more 

Из моего чтения, это потому, что я автоматическое связывание конкретного класса вместо интерфейса UserDetailsService, но это странно для меня, потому что, когда я работал над этим проектом до того, автоподготовка конкретного класса работала нормально.

Я сдал и только что изменил его, чтобы авторизовать интерфейс UserDetailsService в SecurityConfig.java.

Я не уверен, связано это или нет, но теперь при запуске я получаю следующую ошибку, для любого из моих других объектов bean (@Service и т. Д.), Которые имеют @Autowire private UserService userService.

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.clubmate.web.service.UserService com.clubmate.web.service.PageService.userService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.clubmate.web.service.UserService] 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)} 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573) 
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) 
    ... 58 more 
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.clubmate.web.service.UserService] 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)} 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545) 
    ... 60 more 

Любая помощь очень ценится. Это заставляло меня гать часами.

Update

Дополнительная информация: У меня есть еще один конфигурационный класс (AppConfig.java) со следующим:

@Configuration 
@EnableWebMvc 
@ComponentScan("com.clubmate.web") 
@PropertySource(value = { "classpath:application.properties" }) 
@Import({ 
     SecurityConfig.class, 
     CacheConfig.class, 
     DatabaseConfig.class, 
     CronConfig.class 
}) 
public class AppConfig extends WebMvcConfigurerAdapter { 
    // ... 
} 

У меня также есть два класса инициализатора приложения, один для MVC, который:

public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 

    @Override 
    public Class<?>[] getRootConfigClasses() { 
     return new Class[] { 
       AppConfig.class 
     }; 
    } 

    @Override 
    public Class<?>[] getServletConfigClasses() { 
     return new Class[] { 
       StartupHousekeeping.class, 
       ShutdownHousekeeping.class 
     }; 
    } 

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

} 

... и другое по безопасности, которая является:

public class AppInitializer extends AbstractSecurityWebApplicationInitializer { 

    private static Logger log = LogManager.getLogger(AppInitializer.class); 

    @Override 
    protected void beforeSpringSecurityFilterChain(ServletContext context) { 
     // load multipart filter before other filters are created 
     // see: http://docs.spring.io/spring-security/site/docs/4.0.1.RELEASE/reference/htmlsingle/#csrf-multipart 
     MultipartFilter multipartFilter = new MultipartFilter(); 
     multipartFilter.setMultipartResolverBeanName("multipartResolver"); 
     insertFilters(context, multipartFilter); 
    } 

} 

Не могли бы они как-то столкнуться?

Update 2

Скриншот, где исключение бросают: http://i.imgur.com/r6AsOob.jpg

var1 класс SecurityConfig, var2 является прокси-объект, который должен быть вместо этого мой класс UserService.

+0

Может быть, у вас есть такая же проблема http://stackoverflow.com/questions/35344135/custom-userdetailsservice-it-seems-to-be-not-autowired/35350968#35350968 –

+0

Это для внушения. Я обновил свой OP с дополнительной информацией. Я думаю, вы можете что-то ...? – Kieran

+0

Удалить '@ComponentScan (" com.clubmate.web ")' из 'SecurityConfig' –

ответ

5

Аутентификация завершается неудачей, поскольку по умолчанию Spring создает прокси-серверы с использованием JDK-динамических прокси (которые проксируют целевой класс, реализуя его интерфейс (интерфейсы)). Ключами на основе CGLIB, с другой стороны, являются подклассы целевого класса.

См: What is the difference between JDK dynamic proxy and CGLib?

Чтобы включить CGLIB основы проксирования аннотировать один из ваших @Configuration классов с @EnableAspectJAutoProxy(proxyTargetClass=true):

@Configuration 
@EnableAspectJAutoProxy(proxyTargetClass=true) 
public class AppConfig { 
    ... 
} 

Обратите внимание, что в версии 3.2 переупаковываются и включена CGLIB в весенне-ядре JAR. Поэтому он будет работать прямо из коробки.

1

Благодаря @fateddy в комментариях, решение было добавить

@EnableAspectJAutoProxy(proxyTargetClass=true)

мой класс AppConfig, а затем импортировать библиотеки org.aspectj к моему проекту.

Смежные вопросы