Spring Boot:在某些类中,Autowired CRUDRepository为null

时间:2017-04-08 14:08:42

标签: java spring spring-boot dependency-injection autowired

我正在运行一个SpringBoot应用程序,其根类注释为@SpringBootApplication@EnableAutoConfiguration

我已经创建了一个UserRepositoryInterface界面,扩展我的用户 JPA 对象的CrudRepository界面。这个界面没有实现,也没有必要。此应用程序中的任何内容都没有任何配置文件。除了JPA DB连接,但是有效。

public interface UsersRepositoryInterface extends CrudRepository<User, Long> {

    // Query to search for users via email
    List<User> findByEmail(@Param("email") String email);
}

我已成功将其自动装入某些REST端点。当我尝试将其自动装入我的安全类时,问题出现了。我正在尝试使用JWT进行身份验证,但它确实有效。现在我想在登录过程中调用数据库,我遇到了问题。以下是课程:

首先是WebSecurityConfiguererAdapter类,我在其中添加了过滤器的路径。请注意&#34; new JWTLoginFilter&#34;的行,这是我尝试自动装配的类:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomUserDetailsService userDetailsServ;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests()

                //Allow options pre-flight request
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
            // Allow POST request to /login
                .antMatchers(HttpMethod.POST, "/login").permitAll()
            // Others must be authenticated
                .anyRequest().authenticated()
                .and()
            // We filter the api/login requests
                .addFilterBefore(new JWTLoginFilter("/login", authenticationManager()),
                    UsernamePasswordAuthenticationFilter.class)
            // And filter other requests to check the presence of JWT in header
                .addFilterBefore(new JWTAuthenticationFilter(),
                    UsernamePasswordAuthenticationFilter.class);
    }

   @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    // Change logging in from username+password to email+password
        auth.userDetailsService(userDetailsServ);
    }
}

JWTLoginFilter课程。我省略了一些不相关的代码:

public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {

    @Autowired
    private UsersRepositoryInterface userRepo;

    public JWTLoginFilter(String url, AuthenticationManager authManager) {
        super(new AntPathRequestMatcher(url));
        setAuthenticationManager(authManager);
    }

    @Override
    public Authentication attemptAuthentication(
        HttpServletRequest req, HttpServletResponse response)
        throws AuthenticationException, IOException, ServletException {

        //Check if userRepo is injected
        if(userRepo == null) {
            System.out.println("Null");
        }

        AccountCredentials creds = new ObjectMapper()
            .readValue(req.getInputStream(), AccountCredentials.class);
        return getAuthenticationManager().authenticate(
            new UsernamePasswordAuthenticationToken(
                    creds.getEmail(),
                    creds.getPassword(),
                    Collections.emptyList()
            )
        );
    }
}

println中的JWTLoginFilter在被调用时将始终返回 Null

我错过了什么吗?

解决方法:

立即行动。

使用

注释JWTLoginFilter
@Component("someName")

使用

将其注入WebSecurityConfig
@Resource(name="someName")
private JWTLoginFilter myFilter;

在JWTLoginFilter构造函数中对URL进行硬编码,但我仍然需要将AuthenticationManager从WebSecurityConfig自动装配到JWTLoginFilter中。

首先必须使AuthenticationManager成为Bean。在这里使用答案:How To Inject AuthenticationManager using Java Configuration in a Custom Filter

@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

然后在这里注入答案:Spring Security authenticationmanager must be specified - for custom filter

@Override
@Autowired
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
    super.setAuthenticationManager(authenticationManager);
}

删除

setAuthenticationManager(authManager);
在JWTLoginFilter

中的构造函数中

2 个答案:

答案 0 :(得分:2)

那么,你期待什么?您正在通过JWTLoginFilter关键字创建new。 Spring根本没有做任何接线。您应该将此过滤条件设为@Bean@Component或其他任何内容,使其成为spring bean并以某种方式将其注入WebSecurityConfig

答案 1 :(得分:1)

我希望你的问题已经解决了。但我正在添加一个示例代码段,供那些面临同样问题的人参考。

当我们的过滤器包含Autowired依赖项时,使用new()在spring配置中实例化我们的过滤器不会自动装配其依赖项,因为这不是字符串托管bean。因此,我们需要在spring应用程序配置类中自动装配我们的过滤器,而后者又自动装配其内部依赖项。

PFB示例代码供参考。

@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {

    @Autowired
    private MyFilter myFilter;

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(MyApplication.class);
    }

    @Bean
    public FilterRegistrationBean myFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(myFilter);
        registration.addUrlPatterns("*");
        return registration;
    }
}

过滤器:

@Component
public class MyFilter extends BaseFilter {

    @Autowired
    private EmployeeRepository employeeRepository;

    //your code goes here
       if(employeeRepository != null) {
          System.out.println("employeeRepository is not null");
       }

}