与另一个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安全以实现这一目标,有什么建议吗?
过滤器由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();
}