如何从服务帐户密钥文件创建凭据?
How to create Credential from service account key file?
我正在做一个自动生成文件的服务,并使用 Spring 引导和 java 8 将其上传到 google 驱动器。这是另一个更大服务的外部服务。
我找不到任何关于使用 Google 驱动器 API 的服务帐户密钥创建凭据的说明,所以我根据以下说明自己编写了这段代码:https://cloud.google.com/docs/authentication/production。该代码基本上执行一个简单的 GET 请求以获取我的 Google 驱动器中的所有文件和文件夹。它 运行 但出现异常
这是代码
package com.example.demo.controller;
import com.example.demo.dto.FileItemDTO;
import com.example.demo.service.GoogleDriveService;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@RestController
public class GoogleDriveController {
@Value("${google.service.account.key}")
private static Resource serviceAccountKey;
@Value("${external.address}")
private String externalAddress;
private final GoogleDriveService googleDriveService;
private static HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
private static JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
private static final List<String> SCOPES = Collections.singletonList(DriveScopes.DRIVE_METADATA_READONLY);
private static final String TOKENS_DIRECTORY_PATH = "tokens";
@Autowired
public GoogleDriveController(GoogleDriveService googleDriveService) throws IOException {
this.googleDriveService = googleDriveService;
}
private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws IOException {
// Load client secrets.
java.io.File file = new java.io.File("path-to-credential-file");
InputStream inputStream = new FileInputStream(file);
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(inputStream));
// Build flow and trigger user authorization request.
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
.setAccessType("offline")
.build();
LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8868).build();
return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
}
@GetMapping(value = {"/static-page/get"})
public @ResponseBody
List<FileItemDTO> getStaticPage() throws Exception {
String pageToken = null;
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
Drive drive = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT)).build();
List<FileItemDTO> responseList = new ArrayList<>();
FileList fileList = drive.files().list().setFields("files(id,name,thumbnailLink)").execute();
for (File file : fileList.getFiles()) {
FileItemDTO item = new FileItemDTO();
item.setId(file.getId());
item.setName(file.getName());
item.setThumbnailLink(file.getThumbnailLink());
responseList.add(item);
}
return responseList;
}
}
服务帐户获得所有者角色。有人可以帮我解决这个异常吗?
据我了解,具有所有者角色的服务帐户密钥具有最高权限。
编辑:
按照@DalmTo 回答后,我删除了 getCredential() 方法,创建 Drive 对象的代码变成了这样,现在一切正常:
// file 1 is the JSON credential file
// GoogleCredential have been deprecated so instead I use HttpRequestInitializer
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(ServiceAccountCredentials.fromStream(new FileInputStream(file1))
.createScoped(DriveScopes.all()));
Drive drive = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer)
.setApplicationName(ApplicationName).build();
您使用的代码专为与已安装的应用程序一起使用而设计,因此是 AuthorizationCodeInstalledApp。您不能通过服务帐户使用已安装应用程序的代码。
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredential credential = GoogleCredential
.fromStream(new FileInputStream(KEY_FILE_LOCATION))
.createScoped(DriveScopes.all());
// Construct the drive service object.
return new Drive.Builder(httpTransport, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME).build();
}
The code basically perform a simple GET request to get all file and folder in my Google drive. It run but got the exception
请记住,服务帐户不是您,它是虚拟用户,它有自己的 google 驱动器帐户。您可以与服务帐户共享个人 google 驱动器帐户上的文件夹,并授予其访问此文件夹的权限。您不能与它共享根文件夹,您必须自己与它共享所有内容。
我正在做一个自动生成文件的服务,并使用 Spring 引导和 java 8 将其上传到 google 驱动器。这是另一个更大服务的外部服务。
我找不到任何关于使用 Google 驱动器 API 的服务帐户密钥创建凭据的说明,所以我根据以下说明自己编写了这段代码:https://cloud.google.com/docs/authentication/production。该代码基本上执行一个简单的 GET 请求以获取我的 Google 驱动器中的所有文件和文件夹。它 运行 但出现异常
这是代码
package com.example.demo.controller;
import com.example.demo.dto.FileItemDTO;
import com.example.demo.service.GoogleDriveService;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@RestController
public class GoogleDriveController {
@Value("${google.service.account.key}")
private static Resource serviceAccountKey;
@Value("${external.address}")
private String externalAddress;
private final GoogleDriveService googleDriveService;
private static HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
private static JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
private static final List<String> SCOPES = Collections.singletonList(DriveScopes.DRIVE_METADATA_READONLY);
private static final String TOKENS_DIRECTORY_PATH = "tokens";
@Autowired
public GoogleDriveController(GoogleDriveService googleDriveService) throws IOException {
this.googleDriveService = googleDriveService;
}
private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws IOException {
// Load client secrets.
java.io.File file = new java.io.File("path-to-credential-file");
InputStream inputStream = new FileInputStream(file);
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(inputStream));
// Build flow and trigger user authorization request.
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
.setAccessType("offline")
.build();
LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8868).build();
return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
}
@GetMapping(value = {"/static-page/get"})
public @ResponseBody
List<FileItemDTO> getStaticPage() throws Exception {
String pageToken = null;
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
Drive drive = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT)).build();
List<FileItemDTO> responseList = new ArrayList<>();
FileList fileList = drive.files().list().setFields("files(id,name,thumbnailLink)").execute();
for (File file : fileList.getFiles()) {
FileItemDTO item = new FileItemDTO();
item.setId(file.getId());
item.setName(file.getName());
item.setThumbnailLink(file.getThumbnailLink());
responseList.add(item);
}
return responseList;
}
}
服务帐户获得所有者角色。有人可以帮我解决这个异常吗?
据我了解,具有所有者角色的服务帐户密钥具有最高权限。
编辑: 按照@DalmTo 回答后,我删除了 getCredential() 方法,创建 Drive 对象的代码变成了这样,现在一切正常:
// file 1 is the JSON credential file
// GoogleCredential have been deprecated so instead I use HttpRequestInitializer
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(ServiceAccountCredentials.fromStream(new FileInputStream(file1))
.createScoped(DriveScopes.all()));
Drive drive = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer)
.setApplicationName(ApplicationName).build();
您使用的代码专为与已安装的应用程序一起使用而设计,因此是 AuthorizationCodeInstalledApp。您不能通过服务帐户使用已安装应用程序的代码。
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredential credential = GoogleCredential
.fromStream(new FileInputStream(KEY_FILE_LOCATION))
.createScoped(DriveScopes.all());
// Construct the drive service object.
return new Drive.Builder(httpTransport, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME).build();
}
The code basically perform a simple GET request to get all file and folder in my Google drive. It run but got the exception
请记住,服务帐户不是您,它是虚拟用户,它有自己的 google 驱动器帐户。您可以与服务帐户共享个人 google 驱动器帐户上的文件夹,并授予其访问此文件夹的权限。您不能与它共享根文件夹,您必须自己与它共享所有内容。