当前位置: 首页 > 知识库问答 >
问题:

无法通过@Autowoe将AuthentiationManager传递到自定义过滤器

东方智敏
2023-03-14

我正在尝试通过@Autowoe注释将过滤器JWTLoginFilter传递给WebSecurityConfig WebSecurityConfirerAdapter。当JWTLoginFilter尝试从WebSecurityConfig获取Auth验证管理器时,问题就出现了。

当我启动服务器时,我得到这个错误:

描述:

应用程序上下文中某些bean的依赖关系形成一个循环:

JWTLoginFilter在文件中定义[C:\用户\用户\工作空间\后端\目标\类\pl\dn\学校系统\服务\jwt\JWTLoginFilter.class]

webSecurityConfig(字段pl.dn.schoolsystem.service.jwt.JWTLoginFilter pl.dn.schoolsystem.config.webSecurityConfig.JWTLoginFilter)

错误图像

我认为这种循环依赖注入。我被困在这个问题上,不知道如何解决。

网站安全配置:

@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:

@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。谢谢你的建议

共有2个答案

荆亦
2023-03-14

感谢罗曼·普什科夫斯基的帮助,我可以更正我的代码。我的代码的最终结果:

网站安全配置:

@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:

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

    }



}
邵宏达
2023-03-14

您的WebSecurityConfig显式请求将JWTLoginFilter注入其中,并且JWTLoginFilter请求将验证管理器注入其构造函数中。

JWTLoginFilter中删除@Component注释,并在WebSecurityConfig中将过滤器定义为bean:

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

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

 类似资料:
  • 演示在网关追加一个header public class CustomFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 演示在网关追加heade

  • SOFARPC 提供了一套良好的可扩展性机制,为各个模块提供 SPI 的能力。 SOFARPC 对请求与响应的过滤链处理方式是通过多个过滤器 Filter 来进行具体的拦截处理,该部分可由用户自定义 Filter 扩展,自定义 Filter 的执行顺序在内置 Filter 之后。具体方式如下: Bolt Filter 新建自定义 Filter 。 public class CustomFilter

  • //有什么方法可以在我的自定义过滤器类中获得“admin,XY8382,basic” 我的筛选器类

  • 问题内容: 假设我以ng-repeat以表格格式显示以下数据。 以上代码取自http://code.ciphertrick.com/2015/06/01/search-sort-and-pagination- ngrepeat-angularjs/ 这样我们就可以搜索。无论用户在搜索文本框中输入哪种内容,都将基于该过滤器生成数据,但是我的要求有些不同。 我将有一个下拉列表,其中将填充所有字段名称,

  • 问题内容: 我试图在Log4J2中实现和配置自定义过滤器- 基于ThresholdFilter,但打算做更多。我已经看到了有关自定义追加程序的主题,这些主题遵循相同的插件注释语法,但是还没有找到有关自定义拟合程序的主题。 MyCustomFilter.java (基于ThresholdFilter) log4j2.xml LoggingRunner.java 配置语法似乎与Apache文档中的语法

  • 本文向大家介绍Django 自定义过滤器,包括了Django 自定义过滤器的使用技巧和注意事项,需要的朋友参考一下 示例 过滤器允许您将函数应用于变量。此函数可以使用0或1参数。语法如下: 过滤器可以链接在一起,因此非常有效: 如果将其翻译成python,上面的代码行将给出以下内容: 在此示例中,我们将编写一个verbose_name适用于模型(实例或类)或QuerySet的自定义过滤器。它将返回