0

我正在使用 spring-security,并且我正在尝试将我自己的 OAuth2AuthorizationFailureHandler 添加到 DefaultOAuth2AuthorizedClientManager,但我找不到这样做的方法。它似乎不是 Bean;它看起来像是在 OAuth2ClientConfiguration.OAuth2ClientWebMvcSecurityConfiguration.addArgumentResolvers() 中实例化的。

这个 github 问题看起来应该让我能够做到这一点,但我仍然无法弄清楚如何:https ://github.com/spring-projects/spring-security/issues/7583

我阅读了https://github.com/spring-projects/spring-security/commit/2dd40c7de5de72b8f18a51c490d640619c5a6301中添加的文档,但我仍然很难过。

我想添加失败处理程序的原因是我想处理刷新令牌过期时由 RefreshTokenOAuth2AuthorizedClientProvider.authorize() 引发的 OAuth2AuthorizationException。具体来说,当刷新令牌过期时,我想使用 HTTP 403 而不是 HTTP 500 进行响应。

4

1 回答 1

2

我想出了如何自定义 DefaultOAuth2AuthorizedClientManager 的失败处理程序,但它实际上并没有实现我的最终目标,即在尝试使用过期的刷新令牌从认证服务器。

要处理 OAuth2AuthorizationException,请使用带有 @ExceptionHandler(OAuth2AuthorizationException.class) 注释的方法创建一个 @ControllerAdvice 类,该方法可以执行您想要的任何操作。这是我所做的:

@ControllerAdvice
public class GlobalControllerAdvice {

  /**
   * spring-security-oauth2 automatically refreshes the access token while resolving
   * \@RegisteredOAuth2AuthorizedClient-annotated parameters to @RequestMapping methods.  When it
   * fails to refresh an OAuth2 access token because the refresh token is expired,
   * RefreshTokenOAuth2AuthorizedClientProvider.authorize() throws an OAuth2AuthorizationException.
   * If we didn't handle it here, we'd respond with a HTTP 500, and that's no good.  Instead, we
   * respond with HTTP 403 so that the UI can log itself out.
   */
  @ExceptionHandler(OAuth2AuthorizationException.class)
  ResponseEntity<?> handleHttpStatusCodeException(OAuth2AuthorizationException e) {
    return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
  }

}

如果出于某种原因您想要自定义 DefaultOAuth2AuthorizedClientManager 故障处理程序,您可能需要创建一个全新的 OAuth2AuthorizedClientArgumentResolver bean(如下所示)并通过 WebMvcConfigurer 注册它(如下所示):

@Bean
@Order(0)
public OAuth2AuthorizedClientArgumentResolver oAuth2AuthorizedClientArgumentResolver(OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager) {
  final OAuth2AuthorizedClientArgumentResolver oAuth2AuthorizedClientArgumentResolver = new OAuth2AuthorizedClientArgumentResolver(oAuth2AuthorizedClientManager);
  return oAuth2AuthorizedClientArgumentResolver;
}

@Bean
public OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager(ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository authorizedClientRepository) {
  final DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(
      clientRegistrationRepository, authorizedClientRepository);

  authorizedClientManager.setAuthorizationFailureHandler(new OAuth2AuthorizationFailureHandler() {
    @Override
    public void onAuthorizationFailure(OAuth2AuthorizationException e,
        Authentication authentication, Map<String, Object> map) {
      // Handle auth failure here
    }
  });

  return authorizedClientManager;
}
于 2021-04-02T08:29:09.497 回答