如何使用 spring-boot-starter-oauth2-client 执行刷新
Posted
技术标签:
【中文标题】如何使用 spring-boot-starter-oauth2-client 执行刷新【英文标题】:How to perform a refresh with spring-boot-starter-oauth2-client 【发布时间】:2021-10-24 05:18:40 【问题描述】:我正在使用 spring-boot-starter-oauth2-client
向 Google 验证我的用户。这很好用,我可以按预期登录并获得有效的访问权限和刷新令牌。
我正在创建访问令牌:
public class TokenServiceImpl implements TokenService
private final OAuth2AuthorizedClientService clientService;
@Override
public GoogleCredentials credentials()
final var accessToken = getAccessToken();
return getGoogleCredentials(accessToken);
private GoogleCredentials getGoogleCredentials(String accessToken)
return GoogleCredentials
.newBuilder()
.setAccessToken(new AccessToken(accessToken, null))
.build();
private String getAccessToken()
final var oauthToken = (OAuth2AuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
return clientService.loadAuthorizedClient(
oauthToken.getAuthorizedClientRegistrationId(),
oauthToken.getName()).getAccessToken().getTokenValue();
令牌最终被用于 Google Photo API 客户端
private PhotosLibraryClient getClient()
final var settings =
PhotosLibrarySettings
.newBuilder()
.setCredentialsProvider(FixedCredentialsProvider.create(tokenService.credentials()))
.build();
return PhotosLibraryClient.initialize(settings);
问题是令牌将在短时间内过期,我想刷新它以使其保持活动状态。
我不确定我可以使用哪种方法模式来执行此操作,而不必编写整个 OAuth 流程(违背了 Spring oauth2-client
之类的目的)。
到目前为止,我的应用程序中没有其他令牌/安全/过滤器逻辑。
我只需要手动写出来,还是有其他方法可以做到这一点?
【问题讨论】:
可能有设置。您应该检查OAuth2AuthorizedClientService
实现。您正在使用的服务只存储它看起来的信息。可能有更高的组件可以使用。
【参考方案1】:
OAuth2AuthorizedClientManager 会为你刷新你的访问令牌,假设你得到一个刷新令牌和你的访问令牌。 OAuth2AuthorizedClientManager 的文档位于
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2client
在配置您的 OAuth2AuthorizedClientManager 时,请确保您已在 OAuth2AuthorizedClientProvider 中包含 refreshToken...
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository)
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.authorizationCode()
.refreshToken()
.build();
DefaultOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
// Assuming the `username` and `password` are supplied as `HttpServletRequest` parameters,
// map the `HttpServletRequest` parameters to `OAuth2AuthorizationContext.getAttributes()`
authorizedClientManager.setContextAttributesMapper(contextAttributesMapper());
return authorizedClientManager;
然后您使用 OAuth2AuthorizedClientManager 获取访问令牌。下面是来自 spring doco 的示例...
@Controller
public class OAuth2ClientController
@Autowired
private OAuth2AuthorizedClientManager authorizedClientManager;
@GetMapping("/")
public String index(Authentication authentication,
HttpServletRequest servletRequest,
HttpServletResponse servletResponse)
OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
.principal(authentication)
.attributes(attrs ->
attrs.put(HttpServletRequest.class.getName(), servletRequest);
attrs.put(HttpServletResponse.class.getName(), servletResponse);
)
.build();
OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest);
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
...
return "index";
如果当前的accessToken已经过期,这会自动使用之前获取的refreshToken请求一个新的accessToken。
【讨论】:
以上是关于如何使用 spring-boot-starter-oauth2-client 执行刷新的主要内容,如果未能解决你的问题,请参考以下文章
Spring-boot-starter RabbitMQ 全局错误处理