Java @Autowired 在 Spring Security 中不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21869416/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 11:10:28  来源:igfitidea点击:

@Autowired not working in Spring Security

javaspringspring-mvcspring-securityautowired

提问by Rob Johansen

I'm implementing Spring Security using Java configuration in my Spring Web MVC project, and for some reason the @Autowiredannotation is not injecting fields in my security config class. I found thisvery similar question on SO, but my setup is muchsimpler and the accepted answer doesn't apply at all in my case.

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

For reference, I followed the first three chapters of Spring's own security documentation (here) and got in-memory authentication working pretty quickly. I then wanted to switch to JDBC authentication and inject a DataSourcewith the @Autowiredannotation (as shown in this example). However, I get this error:

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

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)}

Here is my security config class. As you can see I'm working around the problem by explicitly looking up my data source:

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

@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();
    }
}

And here is my very simple root-context.xml:

这是我非常简单的 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>

What am I doing wrong?

我究竟做错了什么?

回答by Nabarun

Add <context:component-scan base-package="your.package.where.your.bean.is"/>in root-context.xml

<context:component-scan base-package="your.package.where.your.bean.is"/>在 root-context.xml 中添加

You can uncomment the @Autowired in field declaration and remove it from the constractor. You can find more info here

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

If you @Autowireda bean, don't forget to remove the initialization using new.

如果您@Autowired是 bean,请不要忘记使用new.

回答by rhinds

I'm not 100% sure, but it looks like the problem is you are trying to Autowire DataSource, which has not actually been defined as a Spring bean:

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

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

Creates an object that can be referenced in XML, but don't think it actually creates a bean? (could be wrong, don't really do much with JNDI lookups in spring).

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

Is it possible to switch over to pure java config and drop the XML references?

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

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

(taken from this answer: https://stackoverflow.com/a/15440797/258813)

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

And you can move the password encoder like this:

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

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

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

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

回答by Sarvar Nishonboev

Here's an example I used to autowire BCryptPasswordEncoder:

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

UserServiceImpl.java

UserServiceImpl.java

@Service("userService")
public class UserServiceImpl implements UserService {

    @Autowired
    BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    public User findUserByEmail(String email) {
        return null;
    }
}

WebMvcConfig.java

WebMvcConfig.java

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

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

If you notice, WebMvcConfig.java has @Bean annotation just before passwordEncoder() method. It indicates that a method produces a bean to be managed by the Spring container.

如果您注意到,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

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