Spring Boot中如何改写CorsUtils的isPreFlightRequest静态方法?
改写Spring Boot中CorsUtils的isPreFlightRequest方法的可行方案
由于isPreFlightRequest是静态方法,无法通过继承重写,下面提供两种可落地的实现方式:
方案一:自定义CORS处理组件,绕过原方法
Spring中处理CORS的核心组件(如CorsFilter、RequestMappingHandlerMapping)会调用CorsUtils.isPreFlightRequest,我们可以自定义这些组件,替换掉原有的判断逻辑:
1. 自定义CorsFilter(全局CORS配置场景)
复制原CorsFilter的核心逻辑,将调用CorsUtils.isPreFlightRequest的部分替换为自定义判断:
public class CustomCorsFilter extends OncePerRequestFilter { private final CorsConfigurationSource configSource; private CorsProcessor processor = new DefaultCorsProcessor(); public CustomCorsFilter(CorsConfigurationSource configSource) { Assert.notNull(configSource, "CorsConfigurationSource must not be null"); this.configSource = configSource; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { ServerHttpRequest serverRequest = new ServletServerHttpRequest(request); ServerHttpResponse serverResponse = new ServletServerHttpResponse(response); // 替换原CorsUtils.isPreFlightRequest调用为自定义逻辑 if (isCustomPreFlightRequest(serverRequest)) { CorsConfiguration config = this.configSource.getCorsConfiguration(serverRequest); boolean isValid = this.processor.processRequest(config, serverRequest, serverResponse); if (!isValid || serverResponse.isCommitted()) { return; } } filterChain.doFilter(request, response); } // 自定义预检请求判断逻辑,可按需修改条件 private boolean isCustomPreFlightRequest(ServerHttpRequest request) { HttpHeaders headers = request.getHeaders(); return (request.getMethod() == HttpMethod.OPTIONS && headers.containsKey(HttpHeaders.ORIGIN) && headers.containsKey(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD) // 示例:新增自定义头校验 && headers.containsKey("X-Custom-Preflight-Header")); } }
然后在配置类中注册自定义Filter,替换默认的CorsFilter:
@Configuration public class CorsConfig { @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); // 配置你的CORS规则(允许的源、方法、头等) config.addAllowedOriginPattern("*"); config.addAllowedMethod("*"); config.addAllowedHeader("*"); source.registerCorsConfiguration("/**", config); return new CustomCorsFilter(source); } }
2. 自定义RequestMappingHandlerMapping(@CrossOrigin注解场景)
如果项目使用@CrossOrigin注解控制跨域,RequestMappingHandlerMapping会调用CorsUtils的方法,可自定义该Mapping替换判断逻辑:
public class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping { @Override protected CorsConfiguration getCorsConfiguration(Object handler, HttpServletRequest request) { ServerHttpRequest serverRequest = new ServletServerHttpRequest(request); // 替换原CorsUtils.isPreFlightRequest判断 if (isCustomPreFlightRequest(serverRequest)) { return super.getCorsConfiguration(handler, request); } return null; } private boolean isCustomPreFlightRequest(ServerHttpRequest request) { HttpHeaders headers = request.getHeaders(); // 自定义判断逻辑 return (request.getMethod() == HttpMethod.OPTIONS && headers.containsKey(HttpHeaders.ORIGIN) && headers.containsKey(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD)); } }
在配置类中注册自定义Mapping:
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Bean public RequestMappingHandlerMapping requestMappingHandlerMapping() { CustomRequestMappingHandlerMapping mapping = new CustomRequestMappingHandlerMapping(); mapping.setOrder(0); // 可添加其他配置,如路径匹配规则等 return mapping; } }
方案二:字节码增强修改静态方法逻辑
通过ByteBuddy、ASM等字节码工具,在类加载时修改CorsUtils.isPreFlightRequest的实现,让JVM执行自定义逻辑:
以ByteBuddy为例,先添加依赖:
<dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy</artifactId> <version>1.14.11</version> </dependency> <dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy-agent</artifactId> <version>1.14.11</version> </dependency>
编写Agent代码:
public class CorsUtilsAgent { public static void premain(String args, Instrumentation inst) { new AgentBuilder.Default() .type(ElementMatchers.named("org.springframework.web.cors.CorsUtils")) .transform((builder, typeDescription, classLoader, module) -> builder.method(ElementMatchers.named("isPreFlightRequest") .and(ElementMatchers.takesArgument(0, ServerHttpRequest.class))) .intercept(MethodDelegation.to(CorsUtilsInterceptor.class)) ) .installOn(inst); } } public class CorsUtilsInterceptor { public static boolean isPreFlightRequest(ServerHttpRequest request) { HttpHeaders headers = request.getHeaders(); // 自定义判断逻辑,完全替代原方法实现 return (request.getMethod() == HttpMethod.OPTIONS && headers.containsKey(HttpHeaders.ORIGIN) && headers.containsKey(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD) // 示例:仅允许指定源的预检请求 && "https://your-allowed-domain.com".equals(headers.getFirst(HttpHeaders.ORIGIN))); } }
启动应用时添加JVM参数指定Agent:
-javaagent:/path/to/your-agent-jar-file.jar
注意事项
- 方案一侵入性更低,符合Spring扩展机制,推荐优先使用;
- 方案二需要了解字节码增强原理,且Spring版本更新可能导致逻辑失效,升级时需验证;
- 修改预检请求判断逻辑可能影响跨域安全性,需确保自定义规则符合业务安全要求。
内容的提问来源于stack exchange,提问作者Dexter
相关产品推荐
相关产品推荐

