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

Spring Boot中CORS配置异常:OPTIONS请求返回403错误求助

Fixing OPTIONS 403 Error with Your Custom CORS Filter

Hey there, let's work through this OPTIONS 403 issue you're facing with your CORS filter. I've reviewed your code and identified a few key adjustments and configurations you need to make:

1. Short-Circuit OPTIONS Requests After Setting Headers

Right now, even after handling the OPTIONS request headers, you're still passing the request down the filter chain. This can cause downstream filters (like Spring Security, if you're using it) to block the OPTIONS call with a 403.

Modify your doFilter method to return a 200 OK response immediately after setting the CORS headers for OPTIONS requests:

if ("OPTIONS".equals(request.getMethod())) {
    LOGGER.info("Received OPTIONS request from origin:" + request.getHeader("Origin"));
    response.setHeader("Access-Control-Allow-Methods", "GET,POST,HEAD,OPTIONS,PUT,DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    String headers = StringUtils.trim(request.getHeader("Access-Control-Request-Headers"));
    
    // Optional: Temporarily disable this regex check to test if it's causing the block
    // if (!PATTERN.matcher(headers).matches()) {
    //     throw new ServletException("Invalid value provided for 'Access-Control-Request-Headers' header");
    // }
    
    response.setHeader("Access-Control-Allow-Headers", headers != null ? headers : "*");
    response.setStatus(HttpServletResponse.SC_OK); // Explicitly set success status
    return; // Skip the rest of the filter chain
}

2. Configure Spring Security (If Used) to Allow OPTIONS Requests

If your project uses Spring Security, it will automatically block OPTIONS requests by default. Add this configuration to your security setup to permit all OPTIONS calls:

import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .cors().and() // Enable CORS support
            .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // Allow all OPTIONS requests
                .anyRequest().authenticated(); // Your existing auth rules
    }
}

3. Ensure Your Filter Is Registered with Highest Precedence

Your filter needs to run before any other filters that might block the request. Register it as a bean with the highest priority:

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;

@Configuration
public class CorsFilterRegistration {
    @Bean
    public FilterRegistrationBean<CorsFilterUtil> corsFilterRegistration() {
        FilterRegistrationBean<CorsFilterUtil> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new CorsFilterUtil());
        registrationBean.addUrlPatterns("/*"); // Apply to all endpoints
        registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE); // Run first
        return registrationBean;
    }
}

4. Validate Header Validation Logic

Your regex PATTERN might be too restrictive for some valid request headers (e.g., headers with underscores or other special characters common in custom headers). Temporarily comment out that validation block to test if it's the source of the 403. If that fixes it, adjust the regex to allow valid header characters (like ^[a-zA-Z0-9 ,-_.*]$).

Modified Full doFilter Method

Here's the updated version of your doFilter with the key fixes applied:

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    HttpServletResponse response = (HttpServletResponse) res;
    HttpServletRequest request = (HttpServletRequest) req;
    String origin;
    String credentialFlag;
    
    if (request.getHeader("Origin") == null) {
        origin = "*";
        credentialFlag = "false";
    } else {
        origin = request.getHeader("Origin");
        credentialFlag = "true";
    }
    
    response.addHeader("Access-Control-Allow-Origin", origin.toString());
    response.setHeader("Access-Control-Allow-Credentials", credentialFlag);
    
    System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"+request.getMethod()+"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
    
    if ("OPTIONS".equals(request.getMethod())) {
        LOGGER.info("Received OPTIONS request from origin:" + request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Methods", "GET,POST,HEAD,OPTIONS,PUT,DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        
        String headers = StringUtils.trim(request.getHeader("Access-Control-Request-Headers"));
        // Temporarily disabled for testing
        // if (!PATTERN.matcher(headers).matches()) {
        //     throw new ServletException("Invalid value provided for 'Access-Control-Request-Headers' header");
        // }
        
        response.setHeader("Access-Control-Allow-Headers", headers != null ? headers : "*");
        response.setStatus(HttpServletResponse.SC_OK);
        return;
    }
    
    chain.doFilter(request, response);
}

内容的提问来源于stack exchange,提问作者chukka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:42:07