Spring Security与Angular 5集成时POST请求无法正常工作问题
解决Spring REST + Angular5 POST请求403(CORS过滤器失效)问题
看起来你的核心问题是浏览器发送的POST请求触发了预检OPTIONS请求,但这个请求被Spring Security拦截了,导致CORS头没有正确返回,最终POST请求被浏览器判定为跨域违规而返回403。GET请求属于简单请求不需要预检,所以能正常响应,这完全符合你描述的现象。
下面是几个针对性的解决方案,按推荐优先级排序:
方案1:使用Spring内置的CORS配置(推荐)
手动写CORS过滤器很容易踩顺序和预检请求处理的坑,Spring已经提供了更完善的CORS支持,结合Spring Security配置一起用更可靠:
第一步:配置全局CORS规则
创建WebMvc配置类,定义允许的跨域规则:
@Configuration public class WebCorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") // 对所有接口生效 .allowedOrigins("*") // 允许所有来源,生产环境建议指定具体域名 .allowedMethods("GET", "POST", "PUT", "DELETE") .allowedHeaders("Content-Type", "x-requested-with") .maxAge(48000); // 预检请求缓存时间 } }
第二步:在Spring Security中启用CORS并放行OPTIONS请求
修改你的Security配置类,确保CORS规则生效,并且让预检OPTIONS请求直接通过:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .cors().and() // 启用Spring Security的CORS支持,自动应用全局规则 .authorizeRequests() .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 放行所有OPTIONS预检请求 .anyRequest().authenticated() // 其他请求需要授权 // 这里添加你的其他Security配置,比如表单登录、JWT认证等 .and() .csrf().disable(); // 前后端分离场景下通常需要禁用CSRF,或配置CSRF令牌传递 } }
方案2:修复自定义CORS过滤器
如果你坚持使用自己写的过滤器,需要解决两个关键问题:
- 让过滤器在Spring Security过滤器之前执行
- 直接处理OPTIONS请求,不要让它进入后续的Security校验链
修改你的过滤器类:
@Component @Order(Ordered.HIGHEST_PRECEDENCE) // 确保这个过滤器是第一个执行的 public class CustomCorsFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; HttpServletRequest request = (HttpServletRequest) req; // 设置CORS响应头 response.addHeader("Access-Control-Allow-Origin", "*"); response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE"); response.addHeader("Access-Control-Allow-Headers", "Content-Type,x-requested-with"); response.addHeader("Access-Control-Max-Age", "48000"); // 处理预检OPTIONS请求:直接返回200,不需要走后续过滤器链 if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); } else { chain.doFilter(req, res); } } @Override public void init(FilterConfig filterConfig) {} @Override public void destroy() {} }
同时,在Spring Security配置中也要放行OPTIONS请求,避免Security提前拦截:
// 加入Security配置的configure方法中 .authorizeRequests() .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
关键原因分析
- 预检请求拦截:POST请求(尤其是带Content-Type这类非简单头的)会触发浏览器发送OPTIONS预检请求,Spring Security默认会拦截所有未授权的请求,包括OPTIONS,导致CORS头无法返回,浏览器拒绝后续POST请求。
- 过滤器顺序问题:如果你的自定义CORS过滤器在Spring Security过滤器之后执行,那么Security已经返回403了,CORS头根本没机会被添加到响应中。
内容的提问来源于stack exchange,提问作者Amit
相关产品推荐
相关产品推荐

