我想使用我的 Spring Boot java 应用程序列出 Google Drive 上已登录用户的文件。
我已经实现了 Google 登录流程,效果很好。我在登录时要求用户允许访问他/她的 Google 云端硬盘。 在控制器方法中,我访问用户的 idToken。 目的是我重用此令牌并将其传递给 Google Drive API 调用,但 API 拒绝此令牌。 API 返回并显示以下错误:
{
...
"message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
...
}
看起来我无法重复使用这个idToken。我想,我将需要另一种类型的令牌,但无法弄清楚,是什么样的,以及如何。有人可以建议吗?
以下是我测试时使用的控制器方法:
@GetMapping("")
public ResponseEntity<List<String>> listFiles(Authentication authentication) throws IOException,
GeneralSecurityException {
// get idToken of authenticated user
OAuth2AuthenticationToken oauth2Auth = (OAuth2AuthenticationToken) authentication;
String idToken = ((DefaultOidcUser) oauth2Auth.getPrincipal()).getIdToken().getTokenValue();
Credentials credentials = IdTokenCredentials.create(AccessToken.newBuilder().setTokenValue(idToken).build());
// Build the Drive service and list files.
Drive service = new Drive.Builder(GoogleNetHttpTransport.newTrustedTransport(),
new GsonFactory(),
new HttpCredentialsAdapter(credentials)).setApplicationName(APPLICATION_NAME)
.build();
FileList result = service.files().list().setPageSize(10).setFields("files(name)").execute();
List<String> fileNames = result.getFiles().stream().map(file -> file.getName()).toList();
return ResponseEntity.ok(fileNames);
}
您需要使用 Spring 的 OAuth2AuthorizedClientService 将 ID 令牌交换为访问令牌。
private final OAuth2AuthorizedClientService clientService;
@GetMapping("")
public ResponseEntity<List<String>> listFiles(Authentication authentication) throws IOException,
GeneralSecurityException {
// get idToken of authenticated user
OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;
OAuth2AuthorizedClient client =
clientService.loadAuthorizedClient(
oauthToken.getAuthorizedClientRegistrationId(),
oauthToken.getName());
String accessToken = client.getAccessToken().getTokenValue();
Credentials credentials = IdTokenCredentials.create(AccessToken.newBuilder().setTokenValue(accessToken).build());
// Build the Drive service and list files.
Drive service = new Drive.Builder(GoogleNetHttpTransport.newTrustedTransport(),
new GsonFactory(),
new HttpCredentialsAdapter(credentials)).setApplicationName(APPLICATION_NAME)
.build();
FileList result = service.files().list().setPageSize(10).setFields("files(name)").execute();
List<String> fileNames = result.getFiles().stream().map(file -> file.getName()).toList();
return ResponseEntity.ok(fileNames);
}