如何使用 Spring Security 5 和 OAuth2 Client 获取刷新令牌并进行 API 调用?

Posted

技术标签:

【中文标题】如何使用 Spring Security 5 和 OAuth2 Client 获取刷新令牌并进行 API 调用?【英文标题】:How to use Spring Security 5 and OAuth2 Client to get refresh tokens and make API calls? 【发布时间】:2020-08-25 12:16:47 【问题描述】:

我目前正在使用 Spring Security + OAUth2 协议构建一个 Spring Boot 应用程序。

Here is the Authorization Guide from Spotify I'm following

我无法理解如何执行授权代码流程的第 2 至 4 步。我能够获得授权并获得授权代码来交换访问和刷新令牌,但我不确定如何获取令牌然后开始进行 API 调用。

阅读 Spring 文档让我对某些事情感到困惑。

    如何获取令牌?我注意到登录后它存储在重定向的 URL 中,是使用查询参数获取它还是存储在 OAuth2ClientService 对象中? 授权指南指出我必须对令牌端点进行 POST 调用以获取刷新和访问令牌。我假设我没有使用 WebClient/RestTemplate 执行此操作,因为我能够使用应用程序属性执行 GET 登录请求。如果是这样,我该如何做到这一点? 然后如何使用这些令牌来访问 API 数据?通常,如果不需要令牌,我会使用 WebClient 进行 REST API 调用。如果我得到一个令牌,我会按照我通常的方式进行,但使用访问令牌作为我的查询。

这是我的 application.properties

#
# OAuth ClientRegistration Properties
#
spring.security.oauth2.client.registration.spotify.client-id=#
spring.security.oauth2.client.registration.spotify.client-secret=#
spring.security.oauth2.client.registration.spotify.provider=spotify-provider
spring.security.oauth2.client.registration.spotify.client-authentication-method=basic
spring.security.oauth2.client.registration.spotify.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.spotify.redirect-uri=http://localhost:8080/redirect
spring.security.oauth2.client.registration.spotify.scope=user-read-private,user-read-email

#
# OAuth ProviderDetails Properties
#
spring.security.oauth2.client.provider.spotify-provider.authorization-            
uri=https://accounts.spotify.com/authorize?show_dialog=true

spring.security.oauth2.client.provider.spotify-provider.token-  
uri=https://accounts.spotify.com/api/token

spring.security.oauth2.client.provider.spotify-provider.user-info-uri=https://api.spotify.com/v1/me
spring.security.oauth2.client.provider.spotify-provider.user-name-attribute=id

这是我的 WebSecurityConfig

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

@Override
protected void configure(HttpSecurity http) throws Exception 

    http.authorizeRequests()
        .antMatchers("/redirect")
        .permitAll()

        .and()

        .authorizeRequests()
        .anyRequest().authenticated()

        .and()

        .oauth2Login()
        .loginPage("/login")
        .permitAll();
     
 

控制器

@Controller
public class HomeController 

@Autowired
private OAuth2AuthorizedClientService authorizedClientService;

@GetMapping("/login")
public String getLogin()

    return "login";


///login/oauth2/code/spotify

@GetMapping("/redirect")
public String getRedirect()

    return "redirect";


@GetMapping("/home")
public String getHome()
       
    return "home";


我仍然是这方面的初学者,我需要一段时间才能理解,所以我提前感谢你的帮助。

【问题讨论】:

【参考方案1】:

让它工作。显然,我应该将 WebClient 与使用 OAuth2AuthorizedClientManager 的 ExchangeFilterFunction 集成,该 OAuth2AuthorizedClientManager 处理访问令牌和刷新令牌的授权代码交换。我跟着并阅读了文档,直到我理解为止。 Here's the section that helped me the most.

这是我对代码所做的更改...

我添加了一个新的配置类来将 webclient 与 exchangefilter 功能集成。

@Configuration
public class WebClientConfig 

@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
        ClientRegistrationRepository clientRegistrationRepository,
        OAuth2AuthorizedClientRepository authorizedClientRepository) 
    
    OAuth2AuthorizedClientProvider authorizedClientProvider = 
            OAuth2AuthorizedClientProviderBuilder.builder()
            .authorizationCode()
            .refreshToken()
            .build();
    
    DefaultOAuth2AuthorizedClientManager authorizedClientManager =
            new DefaultOAuth2AuthorizedClientManager(
                    clientRegistrationRepository, authorizedClientRepository);
   
    authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

    return authorizedClientManager;



@Bean
public WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) 
    
    ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = 
            new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
    
    oauth2Client.setDefaultClientRegistrationId("spotify");
    
    return WebClient.builder()
            .apply(oauth2Client.oauth2Configuration())
            .build();


然后,我只是按照常规方式使用 WebClient,而无需在控制器中执行 OAuth2:

@GetMapping("/redirect")
public String getRedirect()
   
    String resourceUri = "https://api.spotify.com/v1/me/top/artists";
    
    String body = webClient
            .get()
            .uri(resourceUri)
            .retrieve()
            .bodyToMono(String.class)
            .block();
    
    System.out.println(body);
    
    return "redirect";

【讨论】:

你改变 spring.security.oauth2.client.registration.spotify.redirect-uri=localhost:8080/login/oauth2/code/spotify

以上是关于如何使用 Spring Security 5 和 OAuth2 Client 获取刷新令牌并进行 API 调用?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Spring Security 5 和 OAuth2 Client 获取刷新令牌并进行 API 调用?

我们如何使用带有 Spring 5.0 的最新 spring-security-oauth2 jar 来实现授权服务器?

如何集成 Spring Security 和 GWT?

Spring Security 5 OAuth 2.0 ResourceServer 如何与 AuthorizationServer 通信?

spring-security saml2:如何获取当前用户?

如何使用 Spring Security 实现登录页面以使其与 Spring Web 流一起使用?