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

Spring Cloud Gateway基于Cookie(Session ID)的认证问题求助

解决Spring Cloud Gateway中Keycloak认证后Authentication为null的问题

核心原因分析

Spring Cloud Gateway基于WebFlux反应式栈,而Zuul基于Servlet栈,两者的Security上下文机制完全不同:

  • 阻塞式的SecurityContextHolder仅适用于Servlet环境,在WebFlux中无法获取反应式上下文里的认证信息
  • 直接调用ReactiveSecurityContextHolder.getContext().subscribe()会脱离当前反应式请求上下文,导致回调中无法拿到Authentication

具体解决步骤

1. 确保Spring Security反应式配置正确

首先要配置WebFlux Security,启用Keycloak认证支持:

  • 引入依赖:确保项目中包含spring-boot-starter-webflux、spring-boot-starter-security、spring-boot-starter-oauth2-client(或对应Keycloak适配依赖)
  • 添加@EnableWebFluxSecurity注解,配置SecurityWebFilterChain来处理Keycloak的认证流程:
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        return http
                .authorizeExchange(exchanges -> exchanges
                        .anyExchange().authenticated()
                )
                .oauth2Login(withDefaults()) // 适配Keycloak OAuth2登录
                .oauth2ResourceServer(oauth2 -> oauth2.jwt(withDefaults())) // 如果是资源服务器模式
                .build();
    }
}

2. 正确在反应式流中获取Authentication

在网关过滤器或请求处理逻辑中,必须将ReactiveSecurityContextHolder的操作整合到当前反应式请求流中,不能用subscribe异步脱离上下文:

@Component
public class AuthForwardFilter implements GatewayFilterFactory<AuthForwardFilter.Config> {

    private static final Logger log = LoggerFactory.getLogger(AuthForwardFilter.class);

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            // 在当前请求的反应式流中获取Authentication
            return ReactiveSecurityContextHolder.getContext()
                    .map(SecurityContext::getAuthentication)
                    .doOnNext(auth -> {
                        if (auth != null) {
                            log.debug("获取到Authentication: {}", auth.getName());
                            // 将认证信息转发到下游微服务(示例:添加请求头)
                            ServerHttpRequest modifiedRequest = exchange.getRequest().mutate()
                                    .header("X-USER-NAME", auth.getName())
                                    .header("X-USER-AUTHORITIES", auth.getAuthorities().toString())
                                    .build();
                            exchange.mutate().request(modifiedRequest).build();
                        } else {
                            log.warn("未获取到Authentication");
                        }
                    })
                    // 继续执行网关过滤器链
                    .then(chain.filter(exchange));
        };
    }

    public static class Config {
        // 自定义配置参数(如果需要)
    }
}

3. 检查Session与Cookie配置

  • 确保Keycloak生成的Session ID Cookie的Domain、Path配置与网关匹配,网关允许接收该Cookie
  • WebFlux的Session配置需使用spring.session.web.flux前缀,而非Servlet的server.servlet.session
  • 确认网关的CORS配置允许携带Cookie(如果UI和网关跨域):
@Bean
public CorsWebFilter corsWebFilter() {
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("https://your-ui-domain.com");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", config);
    return new CorsWebFilter(source);
}

4. 验证认证过滤器执行顺序

确保Spring Security的认证过滤器在自定义网关过滤器之前执行:

  • 在application.yml中配置网关过滤器顺序,将自定义过滤器放在Security过滤器之后:
spring:
  cloud:
    gateway:
      routes:
        - id: your-service-route
          uri: lb://your-service
          predicates:
            - Path=/api/**
          filters:
            - name: AuthForwardFilter
              order: 100 # 确保在Security过滤器(默认order=-100)之后执行

常见错误点排查

  • 不要混用Servlet和WebFlux的Security API:SecurityContextHolder.getContext()完全不适用于WebFlux环境
  • 避免在反应式流外调用ReactiveSecurityContextHolder:只有在Mono/Flux的管道(map/flatMap/doOnNext等操作符)中才能获取到绑定的请求上下文
  • 检查Keycloak的客户端配置:确保网关的client-id、realm、授权端点等配置与Keycloak后台一致,且客户端类型为public或confidential(根据场景选择)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 22:10:28