Spring Boot中CORS配置异常:OPTIONS请求返回403错误求助
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

