如何在集群环境中使用访问令牌的自动续订?

huangapple go评论121阅读模式
英文:

How to use automatic renewal of access tokens in a clustered environment?

问题

我已成功在Spring授权服务器的单个实例以及客户端和资源服务器的各个实例之间运行。在此设置中,访问令牌的自动续订功能正常工作。

然而,在尝试将授权服务器部署到一个集群环境中时,访问令牌的续订功能不再按预期工作。

实际上,我使用Docker Compose模拟了一个集群环境,其中使用Nginx作为代理,有两个Spring授权服务器实例。

在调试客户端应用程序时,我观察到DefaultRefreshTokenTokenResponseClientgetResponse方法正在调用http://localhost:9000/oauth2/token。但是,授权服务器响应重定向到http://localhost:9000/login,导致getTokenResponse方法抛出NullPointerException

具体的错误消息如下:
> 无法调用“org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse.getAccessToken()”,因为“tokenResponse”为null。

在授权服务器配置中,我已经集成了Spring Session来管理会话,并实现了一个受Rob Winch的实现启发的密钥轮换策略。这两个组件都存储在数据库中。

即使我配置客户端使用HttpSessionOAuth2AuthorizedClientRepository,似乎Spring Session无法在其前面充当代理。我可以在SPRING_SESSION_ATTRIBUTES中看到org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizedClientRepository.AUTHORIZED_CLIENTS,但客户端应用程序仍然失败。

@Bean
public OAuth2AuthorizedClientRepository authorizedClientRepository() {
	return new HttpSessionOAuth2AuthorizedClientRepository();
}

我通过在代理中配置粘性会话来解决了这个问题。

http {
  upstream loadbalancer {
    ip_hash;  ## 粘性会话
    server authz1:9000;
    server authz2:9000;
  }

然而,最初我预期Spring Session也可以解决这个问题。现在,我不确定我在设置上是否犯了错误,或者Spring授权服务器和Spring Session是否适合处理这个特定的配置。我是否应该考虑放弃Spring Session,而选择粘性会话配置,或者是否有我可能忽视的解决方案?

英文:

I have successfully run a single instance of Spring Authorization Server alongside individual instances of the client and resource servers. The automatic renewal of access tokens functions properly in this setup.

However, when attempting to deploy the authorization server in a clustered environment, the access token renewal feature no longer works as expected.

I actually simulated a clustered environment using docker compose with Nginx as proxy and two instances of Spring Authorization Server.

Upon debugging the client application, I observed that the getResponse method of DefaultRefreshTokenTokenResponseClient is making a call to http://localhost:9000/oauth2/token. However, the authorization server responds with a redirect to http://localhost:9000/login, causing the getTokenResponse method to throw a NullPointerException.

The specific error message is as follows:
> Cannot invoke "org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse.getAccessToken()" because "tokenResponse" is null.

In the authorization server configuration, I've incorporated Spring Session to manage sessions and implemented a key rotation strategy inspired by Rob Winch's implementation. Both these components store data in a database.

Even if I configure the client to use HttpSessionOAuth2AuthorizedClientRepository, it seems that Spring Session is unable to act as a proxy in front of it. I can see the org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizedClientRepository.AUTHORIZED_CLIENTS in SPRING_SESSION_ATTRIBUTES, but the client application fails.

@Bean
public OAuth2AuthorizedClientRepository authorizedClientRepository() {
	return new HttpSessionOAuth2AuthorizedClientRepository();
}

I was able to resolve this issue by configuring stick sessions in the proxy.

http {
  upstream loadbalancer {
    ip_hash;  ## Sticky session
    server authz1:9000;
    server authz2:9000;
  }

However, I initially anticipated that Spring Session could address this concern as well. Now, I'm uncertain whether I've made a mistake in my setup, or if Spring Authorization Server and Spring Session are simply not suited to handle this particular configuration. Should I consider abandoning Spring Session in favor of a stick session configuration, or is there a solution that I might be overlooking?

答案1

得分: 2

你可以按照官方示例中的方式配置JdbcOAuth2AuthorizationService,以将授权信息持久化到数据库中。如果关系型数据库不适用于您,您可以为所选择的数据存储构建自己的OAuth2AuthorizationService

通过将授权信息持久化到数据库中,refresh_token 可以用于刷新access_token,无论集群中选择哪个实例来处理请求。

英文:

You can configure JdbcOAuth2AuthorizationService as in the official sample to persist authorizations to a database. If a relational database does not work for you, you can build your own OAuth2AuthorizationService for your chosen data store.

By persisting authorizations in a database, the refresh_token can be used to refresh the access_token no matter which instance in the cluster is chosen to service the request.

huangapple
  • 本文由 发表于 2023年8月11日 03:42:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76878864.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定