如何使用 Spring Security 5 和 OAuth2 客户端获取刷新令牌并进行 API 调用?
How to use Spring Security 5 and OAuth2 Client to get refresh tokens and make API calls?
我目前正在使用 Spring 安全 + OAUth2 协议构建一个 Spring 启动应用程序。
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";
}
}
我在这方面还是个初学者,我需要一段时间才能理解,所以在此先感谢您的帮助。
开始使用了。显然我应该将 WebClient 与 ExchangeFilterFunction 集成,该函数使用 OAuth2AuthorizedClientManager 来处理访问令牌和刷新令牌的授权代码交换。我跟随并阅读了文档,直到我理解它。 Here's the section that helped me the most.
这是我对代码所做的更改...
我添加了一个新配置 class 以将网络客户端与 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 安全 + OAUth2 协议构建一个 Spring 启动应用程序。
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";
}
}
我在这方面还是个初学者,我需要一段时间才能理解,所以在此先感谢您的帮助。
开始使用了。显然我应该将 WebClient 与 ExchangeFilterFunction 集成,该函数使用 OAuth2AuthorizedClientManager 来处理访问令牌和刷新令牌的授权代码交换。我跟随并阅读了文档,直到我理解它。 Here's the section that helped me the most.
这是我对代码所做的更改...
我添加了一个新配置 class 以将网络客户端与 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";
}