You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 19:35:24