配置带withCredentials: true的CORS请求头(Spring Boot+Angular5)
你遇到的这个问题其实是CORS规范的硬性限制:当请求携带凭证(比如Cookie)时,Access-Control-Allow-Origin绝对不能设置为*,必须明确指定允许的源,同时还要配置Access-Control-Allow-Credentials: true来允许凭证传递。下面给你几种适配Spring Boot场景的解决方案,你可以根据项目情况选择:
方案一:自定义CORS过滤器(对应你提到的Filter思路)
这种方式灵活性高,适合需要精细化管控源白名单的场景。完善你的过滤器代码如下:
import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Arrays; import java.util.List; @WebFilter(urlPatterns = {"/*"}) public class CorsRestFilter implements Filter { // 配置你的前端源白名单,生产环境替换为实际域名 private final List<String> allowedOrigins = Arrays.asList("http://localhost:4200", "https://your-prod-frontend.com"); @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; // 获取请求头里的Origin String origin = request.getHeader("Origin"); // 校验Origin是否在白名单内,匹配到才设置允许源 if (allowedOrigins.contains(origin)) { response.setHeader("Access-Control-Allow-Origin", origin); } // 核心:允许凭证(Cookie)传递 response.setHeader("Access-Control-Allow-Credentials", "true"); // 允许的请求方法 response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); // 允许的请求头(按需调整) response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"); // 预检请求缓存时长,减少OPTIONS请求次数 response.setHeader("Access-Control-Max-Age", "3600"); // 直接响应OPTIONS预检请求,避免走后续过滤器链 if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); } else { chain.doFilter(req, res); } } @Override public void init(FilterConfig filterConfig) throws ServletException {} @Override public void destroy() {} }
注意:如果你的项目用了Spring Security,要确保这个Filter的优先级高于Security的Filter,可以给类加上
@Order(Ordered.HIGHEST_PRECEDENCE)注解。
方案二:Spring MVC全局CORS配置(更简洁)
Spring Boot提供了更优雅的全局配置方式,无需手写Filter,直接在配置类中定义:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class CorsGlobalConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") // 允许的源白名单 .allowedOrigins("http://localhost:4200", "https://your-prod-frontend.com") // 允许的请求方法 .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允许所有请求头 .allowedHeaders("*") // 开启凭证传递 .allowCredentials(true) // 预检请求缓存时间 .maxAge(3600); } }
这种方式会自动处理所有CORS相关逻辑,包括OPTIONS预检请求,非常适合大多数Spring Boot项目。
方案三:结合Spring Security的CORS配置
如果你用了Spring Security,必须确保CORS配置被Security识别,否则请求可能被提前拦截。在Security配置类中启用CORS:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import java.util.Arrays; @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http // 启用CORS,使用自定义配置源 .cors(cors -> cors.configurationSource(corsConfigurationSource())) .csrf(csrf -> csrf.disable()) // 按需决定是否禁用CSRF .authorizeHttpRequests(auth -> auth .requestMatchers("/rest/public/**").permitAll() .anyRequest().authenticated() ); return http.build(); } // 定义CORS配置源 @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(Arrays.asList("http://localhost:4200", "https://your-prod-frontend.com")); config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); config.setAllowedHeaders(Arrays.asList("*")); config.setAllowCredentials(true); config.setMaxAge(3600L); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; } }
前端侧确认
你的Angular代码中已经正确设置了withCredentials: true,这一步没问题,确保所有需要携带Cookie的请求都保留这个配置即可。
最后几个注意点
- 不要同时混用多种CORS配置方式(比如Filter+全局配置),避免冲突;
- 生产环境务必移除localhost,替换为实际的前端业务域名;
- 检查后端Cookie的
domain和path设置,确保能被前端正确读取和携带。
内容的提问来源于stack exchange,提问作者Pavel
相关产品推荐
相关产品推荐

