提问者:小点点

如何配置Spring-Security(Spring 6)以在不安全的路由上不执行过滤器?


与另一个stackoverflow主题有点关系,这个主题没有给出正确的解决方案,也不适用于Spring 6 (Spring Boot 3)。

我想出了一个基本的Spring启动应用程序来证明我的观点。

控制器有两个endpoint,其中一个必须固定,另一个可访问。

@RestController
public class TestController {

    @GetMapping("/secured-api")
    public String securedApi() {
        return "secured";
    }

    @GetMapping("/public/open-api")
    public String openApi() {
        return "open";
    }

}

安全上下文如下所示,假设MyFilter正在做一些奇怪的事情,例如:验证JWT令牌,如果令牌无效/过期,则触发异常。

@Configuration
public class ComponentSecurityContext {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        return http
            .addFilterAt(new MyFilter(), BasicAuthenticationFilter.class)
            .authorizeHttpRequests(customizer -> customizer
                .requestMatchers(new AntPathRequestMatcher("/public/**"))
                .permitAll()
                .anyRequest()
                .authenticated())
            .build();
    }

    public static class MyFilter extends OncePerRequestFilter {

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

            System.out.println("Filter is called for uri: " + request.getRequestURI());

            // performs some authentication

            filterChain.doFilter(request, response);
        }
    }

}

在服务器上执行以下两个循环

curl http://localhost:9003/public/open-api
curl http://localhost:9003/secured-api

正在触发MyFilter

Filter is called for uri: /public/open-api
Filter is called for uri: /secured-api

我希望<code>MyFilter</code>仅对安全endpoint调用<code></code<,我不在乎是否使用过期令牌访问未受保护的endpoint。

关于如何正确连接Spring安全以实现这一目标,有什么建议吗?


共1个答案

匿名用户

过滤器由securityMatcher限定范围的工作解决方案:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

    return http
        .securityMatcher(new NegatedRequestMatcher(new AntPathRequestMatcher("/public/**")))
        .addFilterAt(new MyFilter(), BasicAuthenticationFilter.class)
        .authorizeHttpRequests((requests) -> requests.anyRequest().authenticated())
        .build();
}