Spring Cloud Gateway Oauth2Login 成功登录后返回 JWT Token 而不是 SESSION Cookie

Posted

技术标签:

【中文标题】Spring Cloud Gateway Oauth2Login 成功登录后返回 JWT Token 而不是 SESSION Cookie【英文标题】:Spring Cloud Gateway Oauth2Login Return JWT Token Instead of SESSION Cookie Upon Successful Login 【发布时间】:2020-11-04 07:36:50 【问题描述】:

如果之前有人问过这个问题,请提前道歉,但我无法找到答案。

我正在尝试将 Spring Cloud Gateway 设置为 OAuth2 客户端,以通过 Keycloak 身份验证服务器对用户进行身份验证/登录。我已经能够使用以下代码片段来实现这一点:

安全配置:

@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfig 
    
    private final GatewayAuthenticationSuccessHandler gatewayAuthenticationSuccessHandler;
    
    public SecurityConfig(GatewayAuthenticationSuccessHandler gatewayAuthenticationSuccessHandler) 
        this.gatewayAuthenticationSuccessHandler = gatewayAuthenticationSuccessHandler;
    
    
    @Bean
    public SecurityWebFilterChain securityWebFilterChain(
            ServerHttpSecurity http, 
            ReactiveClientRegistrationRepository clientRegistrationRepository) 
        
        http
            .authorizeExchange()
            .pathMatchers("/ui/**").permitAll()
            .anyExchange().authenticated()
                .and()
            .oauth2Login().authenticationSuccessHandler(gatewayAuthenticationSuccessHandler)
                .and()
            .oauth2ResourceServer().jwt();
          
        http.logout(
                logout ->
                    logout.logoutSuccessHandler(
                        new OidcClientInitiatedServerLogoutSuccessHandler(clientRegistrationRepository)));
        http.logout().logoutUrl("/logout");
              
        http.csrf().disable();
        http.httpBasic().disable();
        http.formLogin().disable();

        return http.build();
    
    

身份验证成功处理程序:

@Component
public class GatewayAuthenticationSuccessHandler implements ServerAuthenticationSuccessHandler 
    
    private ServerRedirectStrategy redirectStrategy = new DefaultServerRedirectStrategy();
    
    @Value("$my.frontend_url")
    private String DEFAULT_LOGIN_SUCCESS_URL;
      
    @Override
    public Mono<Void> onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) 
        URI url = URI.create(DEFAULT_LOGIN_SUCCESS_URL); 
        return this.redirectStrategy.sendRedirect(webFilterExchange.getExchange(), url);
    


通过此设置,网关应用可以对用户进行身份验证,并代表调用者(UI 应用)从身份验证服务器获取 JWT 令牌。根据我的理解,Spring security 然后使用 spring session 创建一个 SESSION cookie 并将其反馈给调用者。此会话 cookie 可用于后续调用以验证用户身份。网关将使用 SESSION cookie 值从缓存中检索关联的 JWT 令牌,并在代理请求时将其中继到下游资源服务器。我还设置了一个令牌刷新过滤器来代表调用者刷新 JWT 令牌,并设置了一个 Redis 疼痛来在网关的多个实例之间共享此会话 cookie。

我现在想做的是将网关检索到的实际 JWT 令牌返回给调用者(而不是 SESSION cookie)。换句话说,我希望通过使用 JWT 端到端(而不是对调用者使用 SESSION cookie --> 网关,然后对网关使用 JWT --> 资源服务器)来使我的网关更加无状态。以 Spring Cloud Gateway 的当前状态,这甚至可能吗?

附言。我使用的是spring boot 2.2.8版本和spring cloud版本HOXTON.SR6

【问题讨论】:

你成功了吗? 我也有同样的问题,如何解决? 【参考方案1】:

不确定这是否有帮助,但尝试将 SessionPolicy 作为 STATELESS 添加到您的 webfilter 链中,如下所示,它应该可以工作。

http.sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS)

如果您将配置类扩展到 WebSecurityConfigurerAdapter,您也可以尝试使用 NullAuthenticatedSessionStrategy 覆盖 sessionAuthenticationStrategy。

override fun sessionAuthenticationStrategy(): SessionAuthenticationStrategy 
    return NullAuthenticatedSessionStrategy()

【讨论】:

这段代码:http.sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) 应该怎么配置?

以上是关于Spring Cloud Gateway Oauth2Login 成功登录后返回 JWT Token 而不是 SESSION Cookie的主要内容,如果未能解决你的问题,请参考以下文章

spring cloud gateway 如何工作

Spring Cloud Gateway集成

spring cloud gateway 的执行流程

spring cloud gateway 某些路由中跳过全局过滤器

spring cloud gateway 报错 Unable to find GatewayFilterFactory with name

Spring Cloud(18)——gateway