如何在 redis-session 中持久化 OAuth2AuthorizedClient
How to persist OAuth2AuthorizedClient in redis-session
我的项目使用具有 spring 引导会话和 spring 安全性 5.1.10 的 redis 会话。我刚刚迁移了旧的 oauth2 实现。之前,当我重新启动应用程序时,我仍然有 access_token 和 refresh_token。使用此实现,用户已登录,但我在重新启动后松开了 AuthorizedClients,因此 loadAuthorizedClient 函数 returns null。同样在生产中,我们有许多具有相同应用程序的容器。有什么 springboot stardard 方法可以做到这一点吗?比如注册一些bean什么的。
application.yml
...
session:
store-type: redis
redis:
namespace: spring:session:${spring.application.name}
redis:
host: ${redissession.host}
password: ${redissession.password}
port: ${redissession.port}
security:
oauth2:
client:
registration:
biocryptology:
provider: example
client-id: client
client-secret: xxx
client-authentication-method: basic
authorization-grant-type: authorization_code
redirect-uri-template: "{baseUrl}/login"
scope:
- openid
provider:
example:
issuer-uri: https://....
...
Controller.java
@Autowired
private OAuth2AuthorizedClientService clientService;
@GetMapping("/user")
public String getOidcUserPrincipal() throws InvalidSessionException {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!(authentication.getPrincipal() instanceof OidcUser)) {
throw new InvalidSessionException();
}
OidcUser principal = ((OidcUser) authentication.getPrincipal());
LOG.info("oidc: {}", principal.getName());
OAuth2AuthenticationToken oauth2Token = (OAuth2AuthenticationToken) authentication;
LOG.info("authentication: {}", oauth2Token);
OAuth2AuthorizedClient client = clientService
.loadAuthorizedClient(oauth2Token.getAuthorizedClientRegistrationId(), authentication.getName());
LOG.info("client: {}", client);
return "logged";
}
目标是跨容器获取 access_token 和 refresh_token,是否可以使用其他任何没有 OAuth2AuthorizedClientService 的方式?
编辑:
<!-- Spring -->
<spring-cloud.version>Greenwich.SR5</spring-cloud.version>
注册一个 bean 就成功了,它将它保存在会话中,但是随后 OAuth2AuthorizedClientService
对每种情况都发生故障,需要一个解决方法直接在会话中搜索或使用 OAuth2AuthorizedClientRepository
自动装配:
@Bean
public OAuth2AuthorizedClientRepository authorizedClientRepository() {
return new HttpSessionOAuth2AuthorizedClientRepository();
}
controller.java
@Autowired
private OAuth2AuthorizedClientRepository clientRepository;
@GetMapping("/user")
public Map<String, Object> getOidcUserPrincipal(HttpServletRequest request) throws InvalidSessionException {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!(authentication.getPrincipal() instanceof OidcUser)) {
throw new InvalidSessionException();
}
OidcUser principal = ((OidcUser) authentication.getPrincipal());
OAuth2AuthorizedClient client = clientRepository
.loadAuthorizedClient(oauth2Token.getAuthorizedClientRegistrationId(), authentication, request);
LOG.info("client: {}", client);
if (Objects.nonNull(client)) {
String token = client.getAccessToken().getTokenValue();
String refreshtoken = client.getRefreshToken().getTokenValue();
LOG.info("token: {} {}", token, refreshtoken);
}
return principal.getClaims();
}
我的项目使用具有 spring 引导会话和 spring 安全性 5.1.10 的 redis 会话。我刚刚迁移了旧的 oauth2 实现。之前,当我重新启动应用程序时,我仍然有 access_token 和 refresh_token。使用此实现,用户已登录,但我在重新启动后松开了 AuthorizedClients,因此 loadAuthorizedClient 函数 returns null。同样在生产中,我们有许多具有相同应用程序的容器。有什么 springboot stardard 方法可以做到这一点吗?比如注册一些bean什么的。
application.yml
...
session:
store-type: redis
redis:
namespace: spring:session:${spring.application.name}
redis:
host: ${redissession.host}
password: ${redissession.password}
port: ${redissession.port}
security:
oauth2:
client:
registration:
biocryptology:
provider: example
client-id: client
client-secret: xxx
client-authentication-method: basic
authorization-grant-type: authorization_code
redirect-uri-template: "{baseUrl}/login"
scope:
- openid
provider:
example:
issuer-uri: https://....
...
Controller.java
@Autowired
private OAuth2AuthorizedClientService clientService;
@GetMapping("/user")
public String getOidcUserPrincipal() throws InvalidSessionException {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!(authentication.getPrincipal() instanceof OidcUser)) {
throw new InvalidSessionException();
}
OidcUser principal = ((OidcUser) authentication.getPrincipal());
LOG.info("oidc: {}", principal.getName());
OAuth2AuthenticationToken oauth2Token = (OAuth2AuthenticationToken) authentication;
LOG.info("authentication: {}", oauth2Token);
OAuth2AuthorizedClient client = clientService
.loadAuthorizedClient(oauth2Token.getAuthorizedClientRegistrationId(), authentication.getName());
LOG.info("client: {}", client);
return "logged";
}
目标是跨容器获取 access_token 和 refresh_token,是否可以使用其他任何没有 OAuth2AuthorizedClientService 的方式?
编辑:
<!-- Spring -->
<spring-cloud.version>Greenwich.SR5</spring-cloud.version>
注册一个 bean 就成功了,它将它保存在会话中,但是随后 OAuth2AuthorizedClientService
对每种情况都发生故障,需要一个解决方法直接在会话中搜索或使用 OAuth2AuthorizedClientRepository
自动装配:
@Bean
public OAuth2AuthorizedClientRepository authorizedClientRepository() {
return new HttpSessionOAuth2AuthorizedClientRepository();
}
controller.java
@Autowired
private OAuth2AuthorizedClientRepository clientRepository;
@GetMapping("/user")
public Map<String, Object> getOidcUserPrincipal(HttpServletRequest request) throws InvalidSessionException {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!(authentication.getPrincipal() instanceof OidcUser)) {
throw new InvalidSessionException();
}
OidcUser principal = ((OidcUser) authentication.getPrincipal());
OAuth2AuthorizedClient client = clientRepository
.loadAuthorizedClient(oauth2Token.getAuthorizedClientRegistrationId(), authentication, request);
LOG.info("client: {}", client);
if (Objects.nonNull(client)) {
String token = client.getAccessToken().getTokenValue();
String refreshtoken = client.getRefreshToken().getTokenValue();
LOG.info("token: {} {}", token, refreshtoken);
}
return principal.getClaims();
}