【问题标题】:Spring Security config autowiring custom UserDetailsService beanSpring Security 配置自动装配自定义 UserDetailsS​​ervice bean
【发布时间】:2016-02-20 16:26:34
【问题描述】:

我最近回到了我一直在从事的 Spring 项目,但在启动应用程序时遇到了问题。这个问题可能是重复的,但我一直找不到答案。

这是我原来的 SecurityConfig.java 中的一个 sn-p:

@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 对象实现了 UserDetailsS​​ervice。这在启动时出现错误:

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

根据我的阅读,这是因为我正在自动装配一个具体类而不是 UserDetailsS​​ervice 接口,但这对我来说很奇怪,因为当我之前在这个项目上工作时,自动装配具体类工作得很好。

我放弃了,只是将其更改为在 SecurityConfig.java 中自动装配 UserDetailsS​​ervice 接口。

我不确定这是否相关,但现在在启动时我收到以下错误,对于我的任何其他具有 @Autowire private UserService userService 的 bean 对象(@Services 等)。

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

非常感谢任何帮助。这让我发疯了好几个小时。

更新

更多信息:我有另一个配置类 (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);
    }

}

这些会不会有冲突?

更新 2

抛出异常的屏幕截图:http://i.imgur.com/r6AsOob.jpg

var1 是 SecurityConfig 类,var2 是 Proxy 对象,它应该是我的 UserService 类。

【问题讨论】:

  • 可能你也有同样的问题stackoverflow.com/questions/35344135/…
  • 这就是建议。我已经用更多信息更新了我的 OP。我想你可能正在做某事......?
  • SecurityConfig中删除@ComponentScan("com.clubmate.web")
  • 是的,我试过了,但同样的错误。
  • 这可能与上下文层次结构有关。按照建议启用 CGLIB 代理应该可以解决问题。

标签: spring spring-security autowired


【解决方案1】:

自动装配失败是因为默认情况下 Spring 使用 JDK 动态代理(通过实现其接口来代理目标类)创建代理。 另一方面,基于 CGLIB 的代理是目标类的子类。

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

要启用基于 CGLIB 的代理,请使用 @EnableAspectJAutoProxy(proxyTargetClass=true) 注释您的 @Configuration 类之一:

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

请注意,从 3.2 版开始,CGLIB 被重新打包并包含在 spring-core JAR 中。因此,它开箱即用。

【讨论】:

    【解决方案2】:

    感谢 cmets 中的@fateddy,解决方案是添加

    @EnableAspectJAutoProxy(proxyTargetClass=true)

    到我的 AppConfig 类,然后将 org.aspectj 库导入到我的项目中。

    【讨论】:

      猜你喜欢
      • 2016-03-29
      • 1970-01-01
      • 2013-02-11
      • 2015-09-14
      • 1970-01-01
      • 2014-10-12
      • 2013-05-12
      • 2014-10-06
      • 2012-12-13
      相关资源
      最近更新 更多