java.lang.IllegalArgumentException: 无法在取消注册的过滤器类之后进行注册

huangapple go评论72阅读模式
英文:

java.lang.IllegalArgumentException: Cannot register after unregistered Filter class

问题

@Component
public class JwtFilter extends OncePerRequestFilter {

    @Autowired
    private MyUserDetailsService userDetailsService;

    @Autowired
    private Jwtutil jwtUtil;

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

        final String authorizationHeader = request.getHeader("Authorization");

        String username = null;
        String jwt = null;

        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            jwt = authorizationHeader.substring(7);
            username = jwtUtil.extractUsername(jwt);
        }

        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

            if (jwtUtil.validateToken(jwt, userDetails)) {

                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        chain.doFilter(request, response);
    }
}
@EnableWebSecurity
public class SecurityConfigureAdapter extends WebSecurityConfigurerAdapter {
    @Autowired
    private MyUserDetailsService myUseserDeatailService;

    @Autowired
    private JwtFilter jwtRequestFilter;

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests().antMatchers("/authentication").permitAll()
                .anyRequest().authenticated()
                .and().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.addFilterBefore(jwtRequestFilter, JwtFilter.class).authorizeRequests();
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}
英文:

I am developing login service using spring boo. when developing it I got below error and the class

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.IllegalArgumentException: Cannot register after unregistered Filter class com.jwt.logincservice.filter.JwtFilter

@Component
public class JwtFilter extends OncePerRequestFilter {

    @Autowired
    private MyUserDetailsService userDetailsService;

    @Autowired
    private Jwtutil jwtUtil;

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

        final String authorizationHeader = request.getHeader("Authorization");

        String username = null;
        String jwt = null;

        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            jwt = authorizationHeader.substring(7);
            username = jwtUtil.extractUsername(jwt);
        }


        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

            if (jwtUtil.validateToken(jwt, userDetails)) {

                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        chain.doFilter(request, response);
    }
}

WebSecurityConfigurerAdapter class

@EnableWebSecurity
public class SecurityConfigureAdapter extends WebSecurityConfigurerAdapter {
    @Autowired
    private MyUserDetailsService myUseserDeatailService;

    @Autowired
    private JwtFilter jwtRequestFilter;

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests().antMatchers("/authentication").permitAll()
                .anyRequest().authenticated()
                .and().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.addFilterBefore(jwtRequestFilter, JwtFilter.class).authorizeRequests();
    }


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

答案1

得分: 10

你正在尝试在 JwtFilter.class 之前添加 jwtRequestFilter,这有点像是在告诉 Spring Security 在自身之前放置自己。

你可以尝试将这行代码更改为:

http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class).authorizeRequests();

此外,Spring Boot 中的每个 Filter bean 也会自动添加到默认的 servlet filter 链中,因此在初始化后,它将出现两次:

  1. 作为 servlet 过滤器在您的链中
  2. 作为 SpringSecurityFilterChain 中的过滤器

如果您只想将其用作 Spring Security 过滤器,请删除 @Component 注解,并在将其添加到 springSecurityFilterChain 之前自行实例化:

http.addFilterBefore(new JwtFilter(), UsernamePasswordAuthenticationFilter.class).authorizeRequests();
英文:

you are trying to add the jwtRequestFilter before the JwtFilter.class which is kind of telling spring security to put itself before itself.

can you try changing this line to:

http.addFilterBefore(jwtRequestFilter,UsernamePasswordAuthenticationFilter.class).authorizeRequests();

additionally, every Filter bean in spring boot is automatically added also to your default servlet filter chain, so after initialization, it will be present twice:

  1. as a Servlet Filter in your chain
  2. as a Filter in your springSecurityFilterChain

if you just want to use it as a spring security filter remove the @Component annotation and instantiate it by yourself before adding it to the springSecurityFilterChain:

http.addFilterBefore(new JwtFilter(),UsernamePasswordAuthenticationFilter.class).authorizeRequests();

答案2

得分: 0

如果您正在使用Java配置进行Bean配置,则必须在WebInitializer类中注册您的过滤器bean。

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    // 您的配置

    @Override
    protected Filter[] getServletFilters() {
        DelegatingFilterProxy filterProxy = new DelegatingFilterProxy();
        filterProxy.setTargetBeanName("jwtFilter");
        return new Filter[]{filterProxy};
    }
}
英文:

If you are using java config for bean configuration you have to register your filter bean in WebInitializer class.

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    //your configs

    @Override
    protected Filter[] getServletFilters() {
        DelegatingFilterProxy filterProxy = new DelegatingFilterProxy();
        filterProxy.setTargetBeanName("jwtFilter");
        return new Filter[]{filterProxy};
    }
}

答案3

得分: 0

*class 部分要放置的过滤器列表可以通过增加 Spring Security 的调试级别来检索。那里的任何过滤器都将起作用。

英文:

The list of filters to put in the *class part can be retrieved by increasing the debug level on spring security. Any filters there will work.

huangapple
  • 本文由 发表于 2020年4月7日 15:54:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/61075273.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定