Spring Boot DELETE/PUT报CORS无Access-Control-Allow-Origin错
问题根因
DELETE、PUT、带Authorization自定义头/Content-Type: application/json的请求属于非简单请求,浏览器会先发送OPTIONS方法的预检请求,校验跨域头通过后才会发真实业务请求。Postman不会发送预检请求,所以直接调用接口正常。
你当前的问题有两个核心错误:
- 前端错误在请求头中添加了仅后端可返回的
Access-Control-Allow-Origin响应头,额外触发了跨域校验 - 后端跨域配置未覆盖OPTIONS预检请求,若使用Spring Security等安全框架,预检请求会被优先拦截,导致Controller层的
@CrossOrigin注解完全不生效
修复步骤
1. 修正前端代码
删除前端请求头中错误的Access-Control-Allow-Origin字段,这个字段是后端返回给浏览器的响应头,前端禁止手动携带。修正后的代码如下:
export async function deleteUser(id, token) { console.log("helo") const response = await fetch(`${URL}/users/${id}`, { method: "DELETE", mode: 'cors', headers: { "content-type": "application/json", "authorization": `Bearer ${token}` // 移除Access-Control-Allow-Origin配置 } }) if (!response.ok) { return Promise.reject(response) } // 补充原有响应解析逻辑,例如return response.json() }
不要尝试设置mode: 'no-cors'绕过跨域,该模式下前端无法读取接口响应内容,无实际业务意义。
2. 配置后端全局跨域过滤器
不要仅依赖Controller上的@CrossOrigin注解,全局CORS过滤器优先级更高,可覆盖所有接口的跨域逻辑。新增配置类:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; @Configuration public class CorsConfig { @Bean public CorsFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); // 允许前端源地址,禁止用通配符*,因为携带Authorization凭据时通配符配置无效 config.addAllowedOrigin("http://localhost:3000"); // 允许携带凭据(Authorization头、Cookie等) config.setAllowCredentials(true); // 放行所有请求方法,包含OPTIONS预检、DELETE、PUT、PATCH等 config.addAllowedMethod("*"); // 放行所有请求头 config.addAllowedHeader("*"); // 预检请求缓存时间,单位秒,有效期内无需重复发送预检请求 config.setMaxAge(3600L); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); // 对所有接口路径生效 source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } }
3. 适配Spring Security配置(若项目引入了安全框架)
Spring Security的过滤器链优先级高于普通Web过滤器,若不额外配置,OPTIONS预检请求会被安全框架拦截返回401/403,跨域配置无法生效。修改Security配置类:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http // 启用CORS,自动加载之前配置的跨域过滤器 .cors(cors -> {}) // 关闭CSRF校验,避免DELETE/PUT等非POST请求被拦截 .csrf(csrf -> csrf.disable()) .authorizeHttpRequests(auth -> auth // 所有OPTIONS预检请求直接放行,不做权限校验 .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 保留原有业务接口的权限配置 .anyRequest().authenticated() ); return http.build(); } }
验证方式
重启后端服务后发起请求,打开浏览器开发者工具的Network面板:
- 先找到OPTIONS类型的预检请求,确认其响应状态码为200/204,响应头包含
Access-Control-Allow-Origin: http://localhost:3000、Access-Control-Allow-Methods: DELETE,PUT,GET,POST等字段 - 预检请求通过后,后续真实DELETE/PUT请求即可正常响应
内容的提问来源于stack exchange,提问作者whoami0605
相关产品推荐
相关产品推荐

