Skip to content

TokenRelay GatewayFilter 工厂

令牌中继(Token Relay)是指 OAuth2 消费者充当客户端,并将接收到的令牌转发给传出(下游)的资源请求。与网关进行交互的消费者可以是纯客户端(如 SSO 应用程序)或资源服务器。

Spring Cloud Gateway 可以使用 TokenRelay GatewayFilter 将 OAuth2 访问令牌(Access Token)转发给它代理的下游服务。

TokenRelay GatewayFilter 接受一个可选参数 clientRegistrationId

以下示例配置了一个 TokenRelay GatewayFilter:

App.java

java
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
    return builder.routes()
            .route("resource", r -> r.path("/resource")
                    .filters(f -> f.tokenRelay("myregistrationid"))
                    .uri("http://localhost:9000"))
            .build();
}

或者使用 YAML 配置:

application.yaml

yaml
spring:
  cloud:
    gateway:
      routes:
      - id: resource
        uri: http://localhost:9000
        predicates:
        - Path=/resource
        filters:
        - TokenRelay=myregistrationid

上面的示例指定了一个 clientRegistrationId,它可用于获取并转发任何可用 ClientRegistration 的 OAuth2 访问令牌。

如果使用 oauth2Login() 对用户进行身份验证,Spring Cloud Gateway 还可以转发当前已认证用户的 OAuth2 访问令牌。 要将此功能添加到网关,您可以省略 clientRegistrationId 参数,如下所示:

App.java

java
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
    return builder.routes()
            .route("resource", r -> r.path("/resource")
                    .filters(f -> f.tokenRelay())
                    .uri("http://localhost:9000"))
            .build();
}

或者使用 YAML 配置:

application.yaml

yaml
spring:
  cloud:
    gateway:
      routes:
      - id: resource
        uri: http://localhost:9000
        predicates:
        - Path=/resource
        filters:
        - TokenRelay=

这样配置后,网关将(除了让用户登录并获取令牌之外)把身份验证令牌(Authentication Token)传递给下游服务(在本例中为 /resource)。

要在 Spring Cloud Gateway 中启用此功能,请添加以下依赖项:

  • org.springframework.boot:spring-boot-starter-oauth2-client

工作原理:过滤器 (Filter) 会从当前经过身份验证的用户中提取指定 clientRegistrationId 的 OAuth2 访问令牌。 如果未提供 clientRegistrationId,则使用当前经过身份验证的用户自己的访问令牌(在登录期间获取)。 在任何一种情况下,提取的访问令牌都会被放入 Authorization 请求头(通常格式为 Bearer <token>)中,发送给下游请求。

有关完整的工作示例,请参阅 此项目

注意

只有设置了正确的 spring.security.oauth2.client.* 属性,TokenRelayGatewayFilterFactory Bean 才会创建,这些属性会触发 ReactiveClientRegistrationRepository Bean 的创建。

注意

TokenRelayGatewayFilterFactory 使用的 ReactiveOAuth2AuthorizedClientService 默认实现使用内存数据存储。 如果需要更健壮的解决方案(例如持久化存储,防止重启后用户需要重新登录),您需要提供自己的 ReactiveOAuth2AuthorizedClientService 实现。

补充教学 —— OAuth2 Token Relay 解决了什么痛点?

在微服务架构中,有两种常见的鉴权模式:

  1. 网关统一鉴权 + 令牌透传(最常用)

    • 架构:用户 -> 网关(OAuth2 Client) -> 微服务 A(Resource Server)。
    • 流程
      1. 用户访问网关,网关发现没登录,跳转到 SSO(如 Keycloak、Okta)登录。
      2. SSO 回调网关,网关拿到 Access Token
      3. 网关使用 TokenRelay 过滤器,把 Access Token 塞进请求头的 Authorization: Bearer xxx 中。
      4. 请求到达微服务 A。
      5. 微服务 A 拿着这个 Token 去校验权限(或者只解析 JWT 信息)。
    • 优势:微服务不需要处理复杂的 OAuth2 登录逻辑(如跳转、这就叫 Token Relay),只负责校验 Token,逻辑解耦。
  2. 网关只做路由,微服务自己鉴权

    • 这种模式下每个微服务都要配置 OAuth2 Client,太繁琐,不推荐。

关键点TokenRelay 就是实现模式 1 中“透传”这一步的核心组件。没有它,微服务就收不到 Token,无法知道当前用户是谁。

Based on Spring Framework.