Spring Security:非跨域OPTIONS请求绕过认证的推荐方式
我完全get你的痛点——CorsFilter确实是专门为跨域预检请求设计的,它会检查Origin这类CORS专属头,对不带这些头的非跨域OPTIONS请求根本不会特殊处理,但实际场景里OPTIONS的用法远不止浏览器预检:比如同域JS的OPTIONS调用、服务器存活检查(ping接口)这些场景,都需要让这类请求绕过认证。
下面是几种Spring生态里推荐的标准方案,完全贴合Spring Security的设计逻辑,不用自己瞎写过滤器:
1. 全局放行所有OPTIONS请求(最直接)
如果你的场景允许所有OPTIONS请求都跳过认证,直接在Spring Security的配置里添加规则即可,这是最简单通用的方式:
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth // 放行所有HTTP OPTIONS方法的请求 .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 其他请求必须认证 .anyRequest().authenticated() ) // 根据你的实际需求添加其他配置,比如JWT认证、表单登录等 .csrf(csrf -> csrf.disable()); // 如果是API场景,通常需要关闭CSRF return http.build(); } }
这个配置会让Spring Security直接跳过所有OPTIONS请求的认证流程,不管它是不是跨域的,完美覆盖你说的存活检查、同域JS调用这类场景。
2. 细粒度放行特定路径的OPTIONS请求
如果不想全局放行,只想让某些特定路径(比如健康检查接口/api/health)的OPTIONS请求绕过认证,可以更精准地配置requestMatchers:
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth // 只放行/api/health路径下的OPTIONS请求 .requestMatchers(HttpMethod.OPTIONS, "/api/health/**").permitAll() // 其他请求必须认证 .anyRequest().authenticated() ) .csrf(csrf -> csrf.disable()); return http.build(); } }
甚至可以自定义匹配规则,比如结合请求头(非CORS头)来判断:
.requestMatchers(request -> HttpMethod.OPTIONS.matches(request.getMethod()) && request.getHeader("X-Check-Type").equals("health") ).permitAll()
3. 控制器层面单独配置(适合特定端点)
如果某个控制器的OPTIONS请求需要单独处理,也可以直接在控制器方法上标注权限规则:
@RestController @RequestMapping("/api/health") public class HealthCheckController { // 专门处理OPTIONS请求,允许所有访问 @RequestMapping(method = RequestMethod.OPTIONS) @PreAuthorize("permitAll()") public ResponseEntity<Void> handleOptionsRequest() { // 可以在这里添加自定义响应头,比如Allow等 return ResponseEntity.ok() .header("Allow", "OPTIONS, GET") .build(); } // 其他需要认证的接口 @GetMapping public ResponseEntity<String> getHealthStatus() { return ResponseEntity.ok("UP"); } }
这种方式适合需要对特定OPTIONS请求做自定义响应的场景,同时也能绕过认证。
为什么这些方案比自定义过滤器好?
这些都是Spring Security原生支持的配置方式,完全融入了Spring的安全过滤器链,不需要你自己去处理过滤器的顺序、认证上下文这些容易踩坑的细节,而且和你已经在用的CorsFilter完全兼容:CorsFilter会处理带Origin头的跨域预检请求,而这些配置会处理所有其他OPTIONS请求,两者各司其职,不会冲突。
内容的提问来源于stack exchange,提问作者Maksim Gumerov

