已添加@CrossOrigin仍遇CORS预检失败,求JS调用REST API解决方案
解决CORS预检失败问题
1. 先修正前端请求的错误配置
你前端请求里加的Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers这些头完全是多余的——这些是后端返回给浏览器的响应头,不是前端发给后端的请求头。前端带这些头会干扰浏览器的预检逻辑,直接删掉:
fetch("https://capgt-api.eng.us.devcare*w*re.net/tagament/v1/assignbadge", { method: "POST", mode: "cors", headers: { "Content-Type": "application/json", "Tenant-Short-Name": "DWXENG", "Authorization": "Bearer eyJhb....." }, body: JSON.stringify(json), })
2. 优化后端@CrossOrigin注解的配置
默认的@CrossOrigin只允许简单头,而你的请求带了Authorization和自定义的Tenant-Short-Name,这些属于非简单头,需要明确指定允许的头、方法:
// 明确指定允许的Origin、方法、请求头 @CrossOrigin(origins = "*", // 建议替换为前端实际域名,比如"https://your-frontend.com" allowedHeaders = {"Content-Type", "Authorization", "Tenant-Short-Name", "Accept"}, methods = {RequestMethod.POST, RequestMethod.OPTIONS}) @PostMapping(value = "/assignbadge", consumes = {MediaType.APPLICATION_JSON_VALUE}, produces = {MediaType.APPLICATION_JSON_VALUE}) public ResponseEntity<Object> assignBadge(@Parameter(description = "Badge Assignment Input", required = true) @RequestBody final AssitTag assitTag, @Context final HttpServletRequest request) throws IBusConnectionException { // 方法逻辑 }
3. 确保全局CORS过滤器的优先级
如果用了全局CORS过滤器,要让它成为第一个执行的过滤器,避免被其他拦截器(比如Spring Security)提前拦截OPTIONS请求。给过滤器加上最高优先级标记:
@Component @Order(Ordered.HIGHEST_PRECEDENCE) public class CorsFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; HttpServletRequest request = (HttpServletRequest) req; response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST, PUT, PATCH, DELETE"); response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Tenant-Short-Name, Accept"); response.setHeader("Access-Control-Max-Age", "3600"); // 缓存预检结果,减少重复请求 if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); } else { chain.doFilter(req, res); } } // 初始化、销毁方法可留空 }
4. 检查Spring Security(若使用)的配置
如果项目集成了Spring Security,它会默认拦截OPTIONS请求,需要在安全配置里明确放行OPTIONS请求:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.cors().and() .authorizeRequests() .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 放行所有OPTIONS请求 .anyRequest().authenticated(); // 其他安全配置 } }
5. 验证预检请求响应
打开浏览器开发者工具(Network标签),查看OPTIONS请求的响应:
- 确认响应头包含
Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers,且值覆盖你的请求头和方法 - 确认OPTIONS请求返回200状态码
Swagger和Postman能正常调用是因为它们不受浏览器同源策略限制,只有浏览器会触发预检请求,按上述步骤调整后即可解决问题。
内容的提问来源于stack exchange,提问作者ps suj
相关产品推荐
相关产品推荐

