摘要:"明明接口测试工具能调通,前端调用就报CORS错误!""跨域配置加了一堆注解,为什么生产环境突然失效?""用了Spring Security后跨域配置全崩了?"
"明明接口测试工具能调通,前端调用就报CORS错误!"
"跨域配置加了一堆注解,为什么生产环境突然失效?"
"用了Spring Security后跨域配置全崩了?"
作为全栈开发的必经之痛,跨域问题看似简单实则暗藏杀机。本文将用6种段位解决方案 + 3个真实翻车案例,带你彻底终结Spring Boot跨域难题!
java
@RestController@CrossOrigin(origins = "http://localhost:8080", allowedHeaders = "*", methods = {RequestMethod.GET, RequestMethod.POST})public class UserController { // 仅对当前Controller生效}致命缺陷:
每个Controller都要重复配置不支持携带Cookie(credentials问题)无法处理OPTIONS预检请求的缓存java
@Configurationpublic class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") // 生产环境建议指定具体域名 .allowedMethods("*") .allowedHeaders("*") .exposedHeaders("Authorization") // 暴露自定义Header .allowCredentials(true) // 允许携带Cookie .maxAge(3600); // 预检请求缓存时间 }}避坑指南:
java
@Componentpublic class CorsFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; response.setHeader("Access-Control-Allow-Origin", "http://your-frontend.com"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"); response.setHeader("Access-Control-Allow-Credentials", "true"); if ("OPTIONS".equalsIgnoreCase(((HttpServletRequest) req).getMethod)) { response.setStatus(HttpServletResponse.SC_OK); } else { chain.doFilter(req, res); } }}适用场景:
需要动态控制跨域策略(如多租户系统)处理特殊Header要求(如自定义签名头)java
@Configuration@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.cors // 启用Spring Security的CORS支持 .and // 必须禁用CSRF否则会与CORS冲突 .csrf.disable .authorizeRequests .anyRequest.authenticated; } @Bean CorsConfigurationSource corsConfigurationSource { CorsConfiguration configuration = new CorsConfiguration; configuration.setAllowedOrigins(Arrays.asList("http://trusted-domain.com")); configuration.setAllowedMethods(Arrays.asList("*")); configuration.setAllowedHeaders(Arrays.asList("*")); configuration.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource; source.registerCorsConfiguration("/**", configuration); return source; }}血泪教训:
同时存在WebMvcConfigurer和Security配置时,以Security配置为准必须显式调用.cors并配置CorsConfigurationSource使用OAuth2等鉴权方案时,要注意Filter顺序# 以Spring Cloud Gateway为例spring: cloud: gateway: globalcors: cors-configurations: '[/**]': allowed-origins: "https://*.your-domain.com" allowed-methods: "*" allowed-headers: "*" allow-credentials: true max-age: 1800架构优势:
统一管控所有微服务的跨域策略避免每个服务重复配置支持动态路由更新server { listen 80; server_name api.your-domain.com; location / { proxy_pass http://spring-boot-app:8080; # 关键CORS配置 add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always; add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always; add_header 'Access-Control-Allow-Credentials' 'true' always; if ($request_method = 'OPTIONS') { return 204; } }}降维打击优势:
完全解耦业务代码支持复杂跨域策略(如多域名动态匹配)性能损耗最低三、三大经典翻车现场复盘翻车1:配置了allowCredentials却报错"Credentials not supported"原因:
响应头Access-Control-Allow-Origin设置为*浏览器安全策略禁止credentials与通配符共存解决方案:
原因:
未正确处理预检请求(OPTIONS方法)Spring Security等组件拦截了OPTIONS请求解决方案:
根本原因:
生产环境Nginx未正确传递Origin头网关层缓存了旧的CORS配置排查步骤:
检查浏览器Network面板实际响应头使用curl命令测试:bash
curl -H "Origin: http://your-domain.com" -I https://api.your-domain.com在Chrome开发者工具中检查响应头是否包含:
Access-Control-Allow-Origin: [正确域名]Access-Control-Allow-Credentials: true # 如需携带凭证Vary: Origin # 防止CDN缓存错误策略跨域不是bug,而是浏览器守护你的安全防线。点赞收藏本文,下次遇到CORS问题时,对照这个“生存手册”逐级排查,从此告别熬夜抓狂!
讨论区开放:你遇过最奇葩的跨域问题是什么? 欢迎留言,点
来源:大龄程序猿小武
免责声明:本站系转载,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请在30日内与本站联系,我们将在第一时间删除内容!