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

服务端配置CORS后Docker部署仍被跨域策略拦截问题

Docker部署Spring Boot+Angular项目CORS拦截问题排查

问题背景

基于Java Spring Boot框架搭建后端服务,Angular框架开发前端应用,本地环境运行所有功能正常。前后端分别构建为Docker镜像以容器形式部署测试时,出现CORS跨域拦截问题:服务端已完成CORS配置,请求仍被跨域策略拦截。
项目技术配置基线:

  • 认证方案:采用JWT令牌实现安全认证,已禁用CSRF防护及Spring Security默认令牌机制
  • 后端CORS配置代码如下:
private String url = "http://10.1.2.37:4200";
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().cors().configurationSource(new CorsConfigurationSource() {
    @Override
    public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(Collections.singletonList(url));
        config.setAllowedMethods(Collections.singletonList("*"));
        config.setAllowCredentials(true);
        config.setAllowedHeaders(Collections.singletonList("*"));
        config.setExposedHeaders(Arrays.asList("Authorization"));
        config.setMaxAge(1200L);
        return config;
    }}).and()
    .authorizeRequests()
    .antMatchers("/user").authenticated()
    .antMatchers(HttpMethod.GET, "/user").authenticated()
    .and().csrf().disable()
    .oauth2ResourceServer().jwt().jwtAuthenticationConverter(jwtAuthenticationConverter);
        http.headers().frameOptions().sameOrigin();
  • 前端采用Nginx部署,nginx.conf配置如下:
events{}
http {
    include /etc/nginx/mime.types;
    server {
        listen 80;
        server_name  10.1.2.37;
     
        root /usr/share/nginx/html;
        index index.html;
        location / {
            try_files $uri $uri/ /index.html;
        }
    }
}

已尝试操作

通过--network参数将前后端Docker容器运行在同一自定义网络下,问题未解决。
容器启动命令如下:

  1. Angular前端容器启动命令
docker run  --network "project"  --name project_frontend -d -p 4200:80 project_front_end
  1. 后端服务容器启动命令
docker run  --network "project"  -d --name project_backend -p 8080:80 project_backend

报错信息

两个容器正常启动运行,浏览器访问控制台抛出跨域错误:

Access to XMLHttpRequest at 'http://10.1.2.37:8080/menu' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

问题根因

  1. 允许源配置与实际请求源不匹配:后端硬编码配置的允许源为http://10.1.2.37:4200,但浏览器实际发起请求的源为http://localhost:4200,二者不匹配,Spring CORS过滤器不会为未命中允许列表的源返回Access-Control-Allow-Origin响应头,直接触发跨域拦截。
  2. 对Docker网络作用认知偏差:自定义Docker网络仅解决容器之间的内部通信问题,跨域是浏览器端的同源策略限制,判定依据是浏览器地址栏的源(协议+IP/域名+端口),和容器内部网络是否互通没有关联。
  3. CORS通配符配置写法错误:当前配置使用Collections.singletonList("*")设置允许方法、允许请求头,且开启了allowCredentials(true)。根据CORS规范,开启凭证携带时,*不能作为任意源匹配的通配符使用;部分Spring Boot版本中,单元素列表的*不会被识别为通配符,会进一步导致预检请求校验失败。
  4. 潜在过滤器顺序风险:若JWT认证过滤器优先级高于CORS过滤器,OPTIONS预检请求会提前被认证逻辑拦截,无法走到CORS响应头添加逻辑,也会出现缺少跨域头的报错。

解决方案

1. 修正后端CORS配置

替换原有硬编码单源配置,兼容多访问场景,修正通配符写法:

// 配置所有需要允许的前端源,开发/测试环境可按需添加
List<String> allowedOrigins = Arrays.asList("http://localhost:4200", "http://10.1.2.37:4200");

http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .cors().configurationSource(request -> {
            CorsConfiguration config = new CorsConfiguration();
            // 使用setAllowedOriginPatterns替代setAllowedOrigins,兼容带凭证的通配匹配
            config.setAllowedOriginPatterns(allowedOrigins);
            // 明确指定允许的HTTP方法,避免*在凭证模式下失效
            config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"));
            config.setAllowCredentials(true);
            config.setAllowedHeaders(Arrays.asList("*"));
            config.setExposedHeaders(Arrays.asList("Authorization"));
            config.setMaxAge(1200L);
            return config;
        })
        .and()
        .authorizeRequests()
        // 放行OPTIONS预检请求,避免被认证拦截
        .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
        .antMatchers("/user").authenticated()
        .antMatchers(HttpMethod.GET, "/user").authenticated()
        .and()
        .csrf().disable()
        .oauth2ResourceServer().jwt().jwtAuthenticationConverter(jwtAuthenticationConverter);
http.headers().frameOptions().sameOrigin();

如果使用单独的CORS配置类,添加@Order(Ordered.HIGHEST_PRECEDENCE)注解,确保CORS过滤器在JWT认证过滤器之前执行。

2. 统一前端访问地址

确保前端访问地址和后端配置的允许源一致:如果通过http://10.1.2.37:4200访问前端,就将Angular环境配置中的后端接口地址写为http://10.1.2.37:8080;如果通过http://localhost:4200访问,就确保该地址在后端CORS允许列表内。

3. (生产环境推荐)Nginx反向代理彻底消除跨域

修改前端Nginx配置,通过同域名反向代理转发接口请求,让浏览器侧所有请求同源,从根源避免跨域问题:

events{}
http {
    include /etc/nginx/mime.types;
    server {
        listen 80;
        server_name  10.1.2.37;
     
        root /usr/share/nginx/html;
        index index.html;
        # 新增接口反向代理,利用Docker同网络通过容器名访问后端
        location /api/ {
            proxy_pass http://project_backend:80/;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
        location / {
            try_files $uri $uri/ /index.html;
        }
    }
}

配置修改后,将Angular前端的接口基地址改为/api即可,不需要再写后端的IP+端口,所有接口请求由Nginx内部转发到后端服务,浏览器侧不会触发跨域校验。


内容的提问来源于stack exchange,提问作者kuzua

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 01:03:36