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

Spring Cloud Gateway中无需GET请求获取OAuth2访问令牌值的方法

无需手动请求获取JWT令牌的实现方案

针对Spring Cloud Gateway场景,你可以通过以下几种方式自动获取并使用JWT令牌,不用手动发起GET请求:

1. 全局过滤器(GlobalFilter)自动处理请求

Spring Cloud Gateway基于过滤器链工作,你可以实现一个全局过滤器,在请求路由到下游服务前自动获取令牌,添加到请求头中,同时提取角色做RBAC校验。

响应式环境下的过滤器实现(Gateway默认是响应式)

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class TokenRelayFilter implements GlobalFilter {

    private final ReactiveOAuth2AuthorizedClientService authorizedClientService;
    private final ReactiveClientRegistrationRepository clientRegistrationRepository;

    public TokenRelayFilter(ReactiveOAuth2AuthorizedClientService authorizedClientService,
                           ReactiveClientRegistrationRepository clientRegistrationRepository) {
        this.authorizedClientService = authorizedClientService;
        this.clientRegistrationRepository = clientRegistrationRepository;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 从安全上下文获取当前认证用户
        return exchange.getPrincipal()
                .cast(Authentication.class)
                .flatMap(authentication -> {
                    // 替换成你的Keycloak客户端注册ID(application.yml里配置的)
                    String clientRegistrationId = "keycloak";
                    // 获取授权客户端
                    return authorizedClientService.loadAuthorizedClient(clientRegistrationId, authentication.getName())
                            .map(OAuth2AuthorizedClient::getAccessToken)
                            .map(OAuth2AccessToken::getTokenValue);
                })
                .doOnNext(token -> {
                    // 将令牌添加到请求头,传递给下游服务
                    exchange.getRequest().mutate()
                            .header("Authorization", "Bearer " + token);
                    // 这里可以提取令牌中的角色,做RBAC校验
                    // 比如解析JWT,获取roles字段,判断是否有权限访问当前路由
                })
                .then(chain.filter(exchange));
    }
}

2. 在业务组件中直接获取令牌

如果需要在非过滤器的组件(比如服务类、拦截器)中获取令牌,可以通过注入ReactiveOAuth2AuthorizedClientService(响应式)或OAuth2AuthorizedClientService(Servlet环境),结合安全上下文获取当前用户,进而拿到令牌:

import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

@Service
public class TokenService {

    private final ReactiveOAuth2AuthorizedClientService authorizedClientService;

    public TokenService(ReactiveOAuth2AuthorizedClientService authorizedClientService) {
        this.authorizedClientService = authorizedClientService;
    }

    public Mono<String> getCurrentToken() {
        return ReactiveSecurityContextHolder.getContext()
                .map(context -> context.getAuthentication())
                .flatMap(authentication -> {
                    String clientId = "keycloak"; // 你的客户端ID
                    return authorizedClientService.loadAuthorizedClient(clientId, authentication.getName())
                            .map(OAuth2AuthorizedClient::getAccessToken)
                            .map(OAuth2AccessToken::getTokenValue);
                });
    }
}

关键说明

  • 确保你的Spring Cloud Gateway已经正确配置了OAuth2客户端(对接Keycloak),包括spring.security.oauth2.client.registration.keycloak和spring.security.oauth2.client.provider.keycloak相关配置。
  • 前端的session-id会和Spring Security的认证上下文绑定,所以通过getPrincipal()或安全上下文能拿到当前登录用户的信息,进而关联到对应的OAuth2授权客户端。
  • 提取角色做RBAC时,可以用JWT解析库(比如jjwt)解析令牌,拿到realm_access.roles字段(Keycloak的角色默认存在这里),再结合Spring Security的权限校验机制实现访问控制。

内容的提问来源于stack exchange,提问作者h.martinez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 21:08:15