【问题标题】:@Autowired not working in Spring Security@Autowired 在 Spring Security 中不起作用
【发布时间】:2014-02-19 01:53:30
【问题描述】:

我在我的 Spring Web MVC 项目中使用 Java 配置实现 Spring Security,由于某种原因,@Autowired 注释没有在我的安全配置类中注入字段。我在 SO 上发现了 this 非常相似的问题,但是我的设置要简单得多,并且接受的答案在我的情况下根本不适用。

作为参考,我遵循了 Spring 自己的安全文档 (here) 的前三章,并且很快就获得了内存身份验证。然后我想切换到 JDBC 身份验证并注入带有@Autowired 注释的DataSource(如this example 所示)。但是,我收到此错误:

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 javax.sql.DataSource com.tyedart.web.config.security.SecurityConfig.dataSource; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] 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)}

这是我的安全配置类。如您所见,我正在通过显式查找我的数据源来解决该问题:

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

//  @Autowired
//  private DataSource dataSource;

//  @Autowired
//  public PasswordEncoder passwordEncoder;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

        InitialContext ctx = new InitialContext();
        DataSource dataSource = (DataSource) ctx.lookup("java:/comp/env/jdbc/TyedArtDB");

        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

        auth
            .jdbcAuthentication()
                .dataSource(dataSource)
                .passwordEncoder(passwordEncoder);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/manage/**").hasRole("ADMIN")
                .and()  
            .formLogin();
    }
}

这是我非常简单的 root-context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">

       <!-- Root Context: defines shared resources visible to all other web components -->

       <jee:jndi-lookup id="dataSource" jndi-name="jdbc/TyedArtDB"/>

       <bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

</beans>

我做错了什么?

【问题讨论】:

    标签: java spring spring-mvc spring-security autowired


    【解决方案1】:

    在 root-context.xml 中添加 &lt;context:component-scan base-package="your.package.where.your.bean.is"/&gt;

    您可以取消注释 @Autowired in 字段声明并将其从构造函数中删除。你可以找到更多信息here

    如果你 @Autowired 一个 bean,不要忘记使用 new 删除初始化。

    【讨论】:

    • 不幸的是,添加 context:component-scan 元素没有任何作用。
    • 你定义了bean数据源了吗?请提供您如何定义此 bean。
    • 我是否需要比我已经定义的更多的东西?这是在我的 root-context.xml 中(请参阅我的原始帖子):
    • 我错过了。我在这里没有看到任何问题。我现在怀疑容器无法创建 DataSource bean,原因有很多,例如 DB Id/Password 错误、DB Url 错误、数据库关闭等。您可以尝试确保 dataSource bean 成功实例化。
    • 我知道数据库用户名、密码和 URL 是正确的,因为我原始帖子中显示的代码确实有效。它只有在我取消注释两个@Autowired 行和字段时停止工作,然后注释InitialContextDataSourceBCryptPasswordEncoder 的显式实例化/查找。正如我在对他的回答的评论中告诉用户“rhinds”的那样,我认为 Spring 正在我的 root-context.xml 之前初始化我的安全配置类(我不确定如何以相反的顺序发生这种情况)。跨度>
    【解决方案2】:

    我不是 100% 确定,但看起来问题是您正在尝试 Autowire DataSource,它实际上并没有被定义为 Spring bean:

    <jee:jndi-lookup id="dataSource" jndi-name="jdbc/TyedArtDB"/>
    

    创建一个可以在XML中引用的对象,但不认为它实际上创建了一个bean? (可能是错的,在春季不要对 JNDI 查找做太多事情)。

    是否可以切换到纯 java 配置并删除 XML 引用?

    @Bean
    public DataSource dataSource() throws Exception {
        Context ctx = new InitialContext();
        return (DataSource) ctx.lookup("jdbc/TyedArtDB");
    }
    

    (取自这个答案:https://stackoverflow.com/a/15440797/258813

    你可以像这样移动密码编码器:

    @Bean public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
    

    取自:http://automateddeveloper.blogspot.co.uk/2014/02/spring-4-xml-to-annotation-configuration.html

    【讨论】:

    • 基于 Spring 文档中 this example 的前后,我的 JNDI 查找正在创建一个 Spring bean。事实上,我已经在其他类中成功地 @Autowired 了它——它只是在我的安全配置类中存在问题。我可以只使用纯 Java 配置,但是我的安全配置类将依赖于 InitialContextBCryptPasswordEncoder 类。我认为 Spring 在我的 root-context.xml 之前初始化我的安全配置类。
    【解决方案3】:

    这是我用来自动装配 BCryptPasswordEncoder 的示例:

    UserServiceImpl.java

    @Service("userService")
    public class UserServiceImpl implements UserService {
    
        @Autowired
        BCryptPasswordEncoder bCryptPasswordEncoder;
    
        @Override
        public User findUserByEmail(String email) {
            return null;
        }
    }
    

    WebMvcConfig.java

    @Configuration
    public class WebMvcConfig extends WebMvcConfigurerAdapter {
    
        @Bean
        public BCryptPasswordEncoder passwordEncoder(){
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
            return bCryptPasswordEncoder;
        }
    }
    

    如果您注意到,WebMvcConfig.java 在 passwordEncoder() 方法之前有 @Bean 注解。它表示一个方法生成一个由 Spring 容器管理的 bean。

    https://docs.spring.io/autorepo/docs/spring/4.2.4.RELEASE/javadoc-api/org/springframework/context/annotation/Bean.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      • 1970-01-01
      • 2018-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-22
      相关资源
      最近更新 更多