如何通过服务账号密钥文件为Google Drive API创建Credential凭证
Google Drive API服务账号鉴权问题及解决
问题描述
我正在使用Spring Boot和Java 8开发一个自动生成文件并上传至Google Drive的服务,该服务是另一个更大服务的外部模块。
我没有找到使用服务账号密钥为Google Drive API创建凭证的相关指引,因此参考官方身份认证文档自行编写了代码,功能是发起简单GET请求获取我Google Drive下的所有文件和文件夹,但运行时出现异常:
原有问题代码
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; } }
该服务账号已被授予所有者角色,据我了解拥有所有者角色的服务账号密钥具备最高权限。
修复方案
删除原有getCredentials()方法,改用服务账号凭证类直接构造鉴权初始化器,修改后的Drive对象创建代码如下,目前运行正常:
// file 1 为JSON格式的凭证文件 // GoogleCredential 已弃用,因此改用 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();
内容的提问来源于stack exchange,提问作者Dattq2303
相关产品推荐
相关产品推荐

