You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

配置带withCredentials: true的CORS请求头(Spring Boot+Angular5)

解决Spring Boot + Angular5跨域带Cookie的CORS问题

你遇到的这个问题其实是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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:27:00