关于Java:无法通过@Autowired将AuthenticationManager传递给自定义过滤器

Cannot pass AuthenticationManager to custom filter by @Autowired

我正在尝试通过@Autowired注释将过滤器JWTLoginFilter传递给WebSecurityConfig WebSecurityConfigurerAdapter。当JWTLoginFilter尝试从WebSecurityConfig获取AuthenticationManager时出现问题。

启动服务器时,出现以下错误:

Description:

The dependencies of some of the beans in the application context form
a cycle:

JWTLoginFilter defined in file
[C:\\Users\\user\\workspace\\backend\\target\\classes\\pl\\dn\\schoolsystem\\service\\jwt\\JWTLoginFilter.class]

webSecurityConfig (field
pl.dn.schoolsystem.service.jwt.JWTLoginFilter
pl.dn.schoolsystem.config.WebSecurityConfig.jwtLoginFilter)

错误图片

我认为这种循环依赖注入。我对此卡住了,我不知道如何解决。

WebSecurityConfig:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private Environment env;

    @Autowired
    private UserSecurityService userSecurityService;

    @Autowired
    JWTLoginFilter jwtLoginFilter;

    private static final String Salt ="salt"; // should be protected better

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(12, new SecureRandom(Salt.getBytes()));
    }

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().
        authorizeRequests().antMatchers("/").permitAll()
        .antMatchers(HttpMethod.POST,"/login").permitAll()
        .antMatchers("/admin/**").hasRole("ADMIN")
        .anyRequest().authenticated()

        .and()

        //.addFilterBefore(new JWTLoginFilter("/login", authenticationManager()),
                //UsernamePasswordAuthenticationFilter.class)
        .addFilterBefore(jwtLoginFilter,
                UsernamePasswordAuthenticationFilter.class)
        .addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);        
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userSecurityService).passwordEncoder(passwordEncoder());
    }

}

JWTLoginFilter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@Component
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter{

    @Autowired
    UserService userService;

    @Autowired
    public JWTLoginFilter(@Value("/login") String url, AuthenticationManager authManager) {
        super(new AntPathRequestMatcher(url));
        setAuthenticationManager(authManager);
    }

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

        System.out.println("Jestem w JwtLogginFilter.attemptAuthentication -------------------------------------");

        AccountCredentials creds = new ObjectMapper()
            .readValue(req.getInputStream(), AccountCredentials.class);

        User user = userService.findByUsername(creds.getUsername());

        return getAuthenticationManager().authenticate(
                new UsernamePasswordAuthenticationToken(
                        creds.getUsername(),
                        creds.getPassword(),
                        user.getAuthorities()
                        )
        );
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request,
            HttpServletResponse response, FilterChain chain,
            Authentication authResult) throws IOException, ServletException {

        System.out.println("Jestem w JWTLogginFilter.successfulAuthentication --------------------------------------");

        System.out.println("authResult.getName():" + authResult.getName());
        TokenAuthenticationService.addAuthentication(response, authResult.getName());

    }



}

我正在使用Spring Boot 1.5.4。感谢您的建议


您的WebSecurityConfig显式请求将JWTLoginFilter注入其中,而JWTLoginFilter请求将AuthenticationManager注入其构造函数中。 AuthenticationManagerWebSecurityConfig提供,因此具有循环依赖项。

JWTLoginFilter中删除@Component批注,并将过滤器定义为WebSecurityConfig中的Bean:

1
2
3
4
@Bean
public JWTLoginFilter jwtLoginFilter() {
    return new JWTLoginFilter("/login", authenticationManager());
}

您可能还需要在此方法中手动注入UserService(例如,通过构造函数)。


感谢您的帮助Roman Puchkovskiy我可以更正我的代码。我的代码的最终结果:

WebSecurityConfig:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private Environment env;

    @Autowired
    private UserSecurityService userSecurityService;


    private static final String Salt ="salt"; // should be protected better

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(12, new SecureRandom(Salt.getBytes()));
    }

    @Bean
    public JWTLoginFilter jwtLoginFilter() throws Exception {
        return new JWTLoginFilter("/login", authenticationManager());
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().
        authorizeRequests().antMatchers("/").permitAll()
        .antMatchers(HttpMethod.POST,"/login").permitAll()
        .antMatchers("/admin/**").hasRole("ADMIN")
        .anyRequest().authenticated()

        .and()

//      .addFilterBefore(new JWTLoginFilter("/login", authenticationManager()),
//              UsernamePasswordAuthenticationFilter.class)
        .addFilterBefore(jwtLoginFilter(),
                UsernamePasswordAuthenticationFilter.class)
        .addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);        
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userSecurityService).passwordEncoder(passwordEncoder());
    }

}

JWTLoginFilter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter{

    @Autowired
    UserService userService;

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

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

        System.out.println("Jestem w JwtLogginFilter.attemptAuthentication -------------------------------------");

        AccountCredentials creds = new ObjectMapper()
            .readValue(req.getInputStream(), AccountCredentials.class);

        User user = userService.findByUsername(creds.getUsername());

        return getAuthenticationManager().authenticate(
                new UsernamePasswordAuthenticationToken(
                        creds.getUsername(),
                        creds.getPassword(),
                        user.getAuthorities()
                        )
        );
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request,
            HttpServletResponse response, FilterChain chain,
            Authentication authResult) throws IOException, ServletException {

        System.out.println("Jestem w JWTLogginFilter.successfulAuthentication --------------------------------------");

        System.out.println("authResult.getName():" + authResult.getName());

        TokenAuthenticationService.addAuthentication(response, authResult);

    }



}