【问题标题】:Spring Boot: Autowired CRUDRepository null, in certain classesSpring Boot:Autowired CRUDRepository null,在某些类中
【发布时间】:2017-09-03 20:11:24
【问题描述】:

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

我创建了一个UserRepositoryInterface 接口,它扩展 CrudRepository 接口与我的用户JPA 对象。这个接口没有实现,也不需要一个。此应用程序中也没有任何配置文件。 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 类,我在其中添加了过滤器的路径。请注意带有“new JWTLoginFilter”的行,这是我尝试自动装配的类:

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

JWTLoginFilter 中的 println 在被调用时将始终返回 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 的构造函数中

【问题讨论】:

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


【解决方案1】:

嗯,你期待什么?您正在通过 new 关键字创建 JWTLoginFilter。 Spring 在这里根本不做任何布线。您应该将此过滤器设置为@Bean@Component 或其他任何使其成为spring bean 并以某种方式将其注入WebSecurityConfig 的方法。

【讨论】:

  • 我对 Spring 很陌生,所以我不知道。有趣的。我有点被愚弄了,但我似乎无法将 JWTLoginFilter 类注入 WebSecurityConfig。有什么建议吗?
【解决方案2】:

我希望您的问题已经得到解决。但是我添加了一个示例代码 sn-p 供遇到相同问题的人参考。

当我们的过滤器包含自动装配的依赖项时,并且在 spring 配置中使用 new() 实例化我们的过滤器不会自动装配它的依赖项,因为这不是一个字符串管理的 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");
       }

}

【讨论】:

    猜你喜欢
    • 2018-02-04
    • 1970-01-01
    • 2014-09-06
    • 2021-12-13
    • 1970-01-01
    • 2021-11-11
    • 2014-12-30
    • 1970-01-01
    • 2012-08-24
    相关资源
    最近更新 更多