TokenRelay GatewayFilter 工厂
令牌中继(Token Relay)是指 OAuth2 消费者充当客户端,并将接收到的令牌转发给传出(下游)的资源请求。与网关进行交互的消费者可以是纯客户端(如 SSO 应用程序)或资源服务器。
Spring Cloud Gateway 可以使用 TokenRelay GatewayFilter 将 OAuth2 访问令牌(Access Token)转发给它代理的下游服务。
TokenRelay GatewayFilter 接受一个可选参数 clientRegistrationId。
以下示例配置了一个 TokenRelay GatewayFilter:
App.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
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
@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
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 解决了什么痛点?
在微服务架构中,有两种常见的鉴权模式:
网关统一鉴权 + 令牌透传(最常用):
- 架构:用户 -> 网关(OAuth2 Client) -> 微服务 A(Resource Server)。
- 流程:
- 用户访问网关,网关发现没登录,跳转到 SSO(如 Keycloak、Okta)登录。
- SSO 回调网关,网关拿到
Access Token。 - 网关使用
TokenRelay过滤器,把Access Token塞进请求头的Authorization: Bearer xxx中。 - 请求到达微服务 A。
- 微服务 A 拿着这个 Token 去校验权限(或者只解析 JWT 信息)。
- 优势:微服务不需要处理复杂的 OAuth2 登录逻辑(如跳转、这就叫 Token Relay),只负责校验 Token,逻辑解耦。
网关只做路由,微服务自己鉴权:
- 这种模式下每个微服务都要配置 OAuth2 Client,太繁琐,不推荐。
关键点:TokenRelay 就是实现模式 1 中“透传”这一步的核心组件。没有它,微服务就收不到 Token,无法知道当前用户是谁。