跳到主要内容
版本:7.0.2

OAuth 2.0 资源服务器多租户

DeepSeek V3 中英对照 Multitenancy OAuth 2.0 Resource Server Multi-tenancy

多租户

当资源服务器根据不同的租户标识符,采用多种策略来验证承载令牌时,该资源服务器即被视为多租户。

例如,您的资源服务器可以接受来自两个不同授权服务器的承载令牌。或者,您的授权服务器可以代表多个颁发者。

在每种情况下,都需要完成两件事,而如何选择完成方式则涉及权衡取舍:

  1. 解析租户。

  2. 传播租户。

通过声明解析租户

区分租户的一种方式是通过签发者声明。由于签发者声明伴随着已签名的JWT,您可以使用 JwtIssuerReactiveAuthenticationManagerResolver 来实现:

JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = JwtIssuerReactiveAuthenticationManagerResolver
.fromTrustedIssuers("https://idp.example.org/issuerOne", "https://idp.example.org/issuerTwo");

http
.authorizeExchange((authorize) -> authorize
.anyExchange().authenticated()
)
.oauth2ResourceServer((oauth2) -> oauth2
.authenticationManagerResolver(authenticationManagerResolver)
);

这很好,因为颁发者端点是被延迟加载的。实际上,只有当发送第一个带有相应颁发者的请求时,才会实例化对应的 JwtReactiveAuthenticationManager。这使得应用程序的启动独立于那些授权服务器的启动和可用性。

动态租户

您可能不希望每次添加新租户时都重启应用程序。在这种情况下,您可以将 JwtIssuerReactiveAuthenticationManagerResolver 配置为使用一个 ReactiveAuthenticationManager 实例的存储库,这样您就可以在运行时对其进行编辑:

private Mono<ReactiveAuthenticationManager> addManager(
Map<String, ReactiveAuthenticationManager> authenticationManagers, String issuer) {

return Mono.fromCallable(() -> ReactiveJwtDecoders.fromIssuerLocation(issuer))
.subscribeOn(Schedulers.boundedElastic())
.map(JwtReactiveAuthenticationManager::new)
.doOnNext((authenticationManager) -> authenticationManager.put(issuer, authenticationManager));
}

// ...

JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver =
new JwtIssuerReactiveAuthenticationManagerResolver(authenticationManagers::get);

http
.authorizeExchange((authorize) -> authorize
.anyExchange().authenticated()
)
.oauth2ResourceServer((oauth2) -> oauth2
.authenticationManagerResolver(authenticationManagerResolver)
);

在这种情况下,你构建了 JwtIssuerReactiveAuthenticationManagerResolver,并为其配置了一个策略,该策略用于根据给定的签发者(issuer)获取相应的 ReactiveAuthenticationManager。这种方法允许我们在运行时向存储库(在前面的代码片段中显示为一个 Map)中添加或移除元素。

备注

简单地使用任意颁发者来构建 ReactiveAuthenticationManager 是不安全的。颁发者必须是代码能够从可信来源验证的,例如一个允许的颁发者列表。