Bean Order 值神秘地为 null

Bean Order value is Mysteriously null

提问人:Dikianify 提问时间:9/1/2023 最后编辑:Ken ChanDikianify 更新时间:9/1/2023 访问量:44

问:

我正在尝试获取两个过滤器,一个用于捕获 jwt,另一个用于捕获 API 密钥。这是我的代码:

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    
    @Autowired
    private JwtRequestFilter jwtRequestFilter;
    
    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
    
    @Autowired
    private ApiKeyRequestFilter apiKeyRequestFilter;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth, UserDetailsService userDetailsService) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }


    @Bean
    @Order(1)
    SecurityFilterChain jwtFilterChain(HttpSecurity http) throws Exception {
            return http
                .cors().and().csrf().disable()
                .authorizeRequests()
                    .antMatchers(
                            "/authenticate",
                            "/register",
                            "/refresh",
                            "/post_appointment",
                            "/delete_appointment",
                            "/get_times",
                            "/get_services",
                            "/sendResetPassword",
                            "/sendSupport",
                            "/paymentWebhook",
                            "/api**")
                        .permitAll()
                    .anyRequest().authenticated()
                .and()
                .exceptionHandling()
                    .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                .and()
                .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class).build();
       }

    @Bean
    @Order(2)
    SecurityFilterChain APIFilterChainConfig(HttpSecurity http) throws Exception {
            return http
                .cors().and().csrf().disable()
                .authorizeRequests()
                    .antMatchers("/api/**")
                        .permitAll()
                    .anyRequest().authenticated()
                .and()
                .addFilterBefore(apiKeyRequestFilter, JwtRequestFilter.class).build();
    }
}

运行这个给了我这个错误:

Error creating bean with name 'APIFilterChainConfig' defined in class path resource [com/reporter/config/SecurityConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.web.SecurityFilterChain]: Factory method 'APIFilterChainConfig' threw exception; nested exception is java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because the return value of "org.springframework.security.config.annotation.web.builders.FilterOrderRegistration.getOrder(java.lang.Class)" is null

这很令人困惑,因为我显然是在设置顺序。是过滤器本身的问题吗?目前还不是很清楚,所以任何帮助将不胜感激。我还要补充一点,这是根据以下页面对我的安全配置进行现代化改造的更大努力的一部分:https://www.danvega.dev/blog/2023/04/20/multiple-spring-security-configs/

java spring-security

评论

1赞 Andrei Lisa 9/1/2023
您使用的是哪个版本的 Spring Security?
0赞 Dikianify 9/1/2023
你肯定在做某事。我将版本设置为5.1.5.RELEASE,现在我收到消息:“描述:com.reporter.config.SecurityConfig中jwtFilterChain方法的参数0需要找不到'org.springframework.security.config.annotation.web.builders.HttpSecurity'类型的bean。动作: 考虑在配置中定义一个类型为'org.springframework.security.config.annotation.web.builders.HttpSecurity'的bean。现在试图解决它。
1赞 Toerktumlare 9/1/2023
您不使用 Spring Security 提供的内置 JWT 功能来验证 JWT 的任何特殊原因是什么?另请注意,将 JWT 分发给浏览器是非常不安全的,并且 JWT 不应用作浏览器等终端客户端中的会话令牌,因为它们缺乏 cookie 所具有的重要安全功能,使用 jwts 作为会话容器会使您的应用程序容易受到令牌托管攻击、csrf 攻击,在某些情况下 DDos 攻击等。
0赞 Dikianify 9/1/2023
我在读你。我将结束问题并重新思考我现在是如何做事的。

答:

0赞 Ken Chan 9/1/2023 #1

它不是关于特定过滤器的顺序,而是过滤器的顺序。问题来自以下行SecurityFilterChainSecurityFilterChainAPIFilterChainConfig

.addFilterBefore(apiKeyRequestFilter, JwtRequestFilter.class)

中指定的过滤器类应该是 spring security 内置过滤器,其顺序在此中显式定义,或者是成功定义为之前添加到同一过滤器的过滤器,以便 spring security 有足够的信息来知道它应该添加到哪个过滤器链位置。addFilterBefore()SecurityFilterChainapiKeyRequestFilter

JwtRequestFilter显然不是 Spring Security 内置过滤器,因此 Spring Security 不知道其订单值来做出这样的决定,因此抛出此异常。

要解决此问题,您必须添加到基于其知道其订单值的内置过滤器之一,如果这有意义的话,也许就在之前:apiKeyRequestFilterSecurityFilterChainUsernamePasswordAuthenticationFilter

.addFilterBefore(apiKeyRequestFilter,UsernamePasswordAuthenticationFilter.class)