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

Spring Cloud Gateway非GET请求返回403 Forbidden问题求助

Spring Cloud Gateway 导致 POST/PUT/DELETE 请求返回 403 Forbidden(GET 请求正常)

背景

前端采用Angular 15,后端基于Spring 3.0.2,前后端认证统一使用Keycloak 20.0.3。项目拆分多个微服务部署在独立Spring工程中,通过Spring Cloud Gateway作为前端统一入口,借助Eureka实现网关的服务发现能力。

注:网关仅通过YAML文件配置,未集成Spring Security或Keycloak,已配置CORS规则。

网关核心配置YAML如下:

spring:
  application:
    name: gateway
  cloud:
    gateway:
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedOrigins: "https://localhost:4200"
            allowedMethods: "*"
            allowedHeaders: "*"
      routes:
      - id: users
        uri: lb://micro-service-1/api/users
        predicates:
        - Method=GET,POST,PUT,DELETE
        - Path=/api/users/**
      - id: assets
        uri: lb://micro-service-2/api/assets
        predicates:
        - Method=GET,POST,PUT,DELETE
        - Path=/api/assets/**

server:
  port: 8100
eureka:
  client:
    registerWithEureka: true
    serviceUrl:
      defaultZone: http://localhost:8761/eureka

问题描述

构建CRUD API过程中,GET请求可正常通过网关访问微服务,但POST、PUT、DELETE请求在Angular端发起时会返回403 Forbidden错误。

注:使用Postman测试所有请求均无异常;跳过网关直接调用微服务时,所有请求均可正常执行。
注:后端仅提供RESTful API,登录/登出/注册等认证流程完全由Keycloak处理。

已尝试的无效方案

  • 网关配置security.enable-csrf: false禁用CSRF,无效。
  • 引入spring-boot-starter-security依赖,配置SecurityFilterChain禁用CSRF、CORS、HttpBasic并允许所有请求,结果仍要求凭证且与Keycloak冲突。
  • 尝试为网关集成Keycloak,因Keycloak依赖Spring Web,与Spring Cloud Gateway产生依赖冲突。

可行解决方案

1. 修复CORS配置,允许凭证传递

当前CORS配置未开启allowCredentials,Angular发送非GET请求时会携带Keycloak认证Cookie、CSRF Token等凭证,若网关未允许凭证跨域传递,浏览器会拦截请求返回403。

修改网关CORS配置:

spring:
  cloud:
    gateway:
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedOrigins: "https://localhost:4200"
            allowedMethods: "*"
            allowedHeaders: "*"
            allowCredentials: true # 开启凭证跨域传递
            exposedHeaders: "XSRF-TOKEN" # 允许Angular读取CSRF Token响应头

2. 修正网关路由路径配置

当前路由的uri包含/api/users路径,同时Path谓词匹配/api/users/**,会导致请求转发到微服务时路径重复(如/api/users/api/users/xxx),部分微服务的安全规则会拦截这类无效路径。

调整路由配置(二选一即可):

方案A:移除uri中的路径,通过过滤器剥离前缀

routes:
- id: users
  uri: lb://micro-service-1
  predicates:
  - Method=GET,POST,PUT,DELETE
  - Path=/api/users/**
  filters:
  - StripPrefix=2 # 剥离请求路径前2段(/api/users),转发到微服务根路径

方案B:调整Path谓词匹配规则

routes:
- id: users
  uri: lb://micro-service-1/api/users
  predicates:
  - Method=GET,POST,PUT,DELETE
  - Path=/** # 匹配所有路径,直接转发到uri指定的/api/users下

3. 确保CSRF Token正确传递

Angular默认会自动通过X-XSRF-TOKEN请求头发送CSRF Token,若网关未正确转发相关头信息,微服务的CSRF防护会拦截非GET请求。

在网关添加响应头配置,确保Angular能获取到CSRF Token:

spring:
  cloud:
    gateway:
      default-filters:
      - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
      - AddResponseHeader=Access-Control-Expose-Headers, XSRF-TOKEN

同时确认微服务侧(若集成Spring Security)的CSRF配置,允许从请求头读取Token:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http.csrf(csrf -> csrf
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            .ignoringRequestMatchers("/api/**")); // 若API无需CSRF防护,可直接忽略
    // 其他认证授权配置
    return http.build();
}

4. 调整Keycloak Cookie的SameSite属性

Keycloak默认设置的认证Cookie(如KEYCLOAK_SESSION)SameSite属性为Strict,会导致跨域请求(Angular到网关)无法携带该Cookie,微服务会判定请求未认证返回403。

在Keycloak管理控制台操作:进入对应Realm → 客户端 → 前端客户端 → 设置 → 登录设置,将SameSite Cookie设置为Lax(HTTP环境)或None(HTTPS环境)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 18:45:20