Google Drive API、Oauth 和服务帐号

Posted

技术标签:

【中文标题】Google Drive API、Oauth 和服务帐号【英文标题】:Google Drive API, Oauth and service account 【发布时间】:2018-01-11 13:26:33 【问题描述】:

我在 Google Drive API、服务帐户和身份验证方面遇到了一些问题。我读了很多,但我不知道如何解决这个问题。

上下文:我的云端硬盘帐户中有一些文件(大约 35GB)和一个简单的网络应用程序,用户可以登录,查看我的云端硬盘中的一些选定文件夹/文件,并在需要时下载它们。 唯一可以直接访问我的云端硬盘帐户的是(或应该是)我的服务器,用户通过网络应用程序/服务器完成他们的工作。

经过一番搜索,我发现 server-to-server authorization docs 应该非常适合我的目的,但是,正如我所见,服务帐户不共享相同的云端硬盘空间:他们有自己的空间,而且不可升级。由于这个(奇怪的)限制,我无法使用服务帐户,因为我有超过 35GB 的空间,我需要“共享”所有内容。

其他方式:使用“标准”OAuth 来获取访问令牌,然后使用它来调用 Drive API,但访问令牌有一个过期日期,我不能每次都手动更新它。

那么,第一个问题:有没有办法增加服务帐户的配额?如果没有,是否有办法像服务帐户一样使用我的“普通”帐户(所有者)?

第二个(虚拟)问题:我阅读了有关creating new OAuth credentials 的文档,最后您获得了一些示例代码和“客户端机密”JSON。我运行了这个例子,但我不明白那个 JSON 文件的作用是什么:无论如何我必须登录并授予权限,我为什么需要它?

第三个(足够愚蠢的)问题:如果 OAuth 是唯一的解决方案,有没有一种方法可以获取/刷新访问令牌,而无需每次都手动进行?我查看了 OAuth 文档,“用户交互/确认”是身份验证流程中的基本内容之一,所以我认为这是不可能的。

【问题讨论】:

见***.com/questions/19766912/… 太棒了!之前没找到,我就这样试试,看看会发生什么……非常感谢! 【参考方案1】:

将您的云端硬盘帐户的文件夹共享到您的服务帐户。 您的服务帐号的地址类似于 XXX@XXX.iam.gserviceaccount.com。 然后,您的服务帐户可以查看您云端硬盘帐户中的共享文件夹。 所以你有 35GB 的服务帐户。

【讨论】:

这这这这!!!!!!哇。我在很多 *** 帖子中都苦苦挣扎……直到这一篇。你救了我!非常感谢@drinkmystery。我很感激你。 这个答案对我很有帮助。我非常讨厌 Google 云端硬盘让我的生活变得悲惨 实现此共享需要多长时间才能显示在服务帐户中.. 这是正确的答案!! 感谢您的洞察力。这很有帮助,因为快速入门页面没有提到这种方法,至少据我所知。【参考方案2】:

drinkmystery 的答案是正确的方法,以防您的帐户是私人帐户而不是 Google Workspace(以前的 GSuite)的一部分。否则,使用createDelegated() 方法可以更优雅地解决此问题。它被描述为here,您应该按照那里的所有配置说明进行操作,但是那里提供的代码示例基于一些已弃用的包,所以我花了一些时间使其与Drive API tutorial 中的代码结合使用才能正常工作.

所以对于那些只需要一个工作代码示例的人来说,这里是(注意使用createDelegated):

import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
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 com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.ServiceAccountCredentials;

import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;

public class DelegatedDriveWithServiceAccountQuickstart 
    private static final String APPLICATION_NAME = "your awesome app";
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

    private static final List<String> SCOPES = Arrays.asList(DriveScopes.DRIVE);
    private static final String CREDENTIALS_FILE_PATH = "/path/to/your/service-account-key-downloaded-from-google-api-console.json";

    public static void main(String... args) throws IOException, GeneralSecurityException 
        // Build a new authorized API client service
        final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
        HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(ServiceAccountCredentials.fromStream(new FileInputStream(CREDENTIALS_FILE_PATH))
                .createScoped(SCOPES)
                .createDelegated("user.whose.drive.you.want.to.share@your-domain-in-gsuite.com"));
        Drive driveService = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer)
                .setApplicationName(APPLICATION_NAME)
                .build();

        // Print the names and IDs for up to 10 files.
        FileList result = driveService.files().list()
                .setPageSize(10)
                .setFields("nextPageToken, files(id, name)")
                .execute();
        List<File> files = result.getFiles();
        if (files == null || files.isEmpty()) 
            System.out.println("No files found.");
         else 
            System.out.println("Files:");
            for (File file : files) 
                System.out.printf("%s (%s)\n", file.getName(), file.getId());
            
        
    

请确保您的项目依赖项是最新的(不要盲目使用 Drive API 教程中的那些)。这是我的 build.gradle:

apply plugin: 'java'
apply plugin: 'application'

mainClassName = 'DelegatedDriveWithServiceAccountQuickstart'
sourceCompatibility = 1.8
targetCompatibility = 1.8
version = '1.0'

repositories 
    mavenCentral()


dependencies 
    compile 'com.google.api-client:google-api-client:1.31.1'
    compile 'com.google.apis:google-api-services-drive:v3-rev20201130-1.31.0'
    compile 'com.google.auth:google-auth-library-oauth2-http:0.22.2'


【讨论】:

感谢您提供使用服务帐户的示例。

以上是关于Google Drive API、Oauth 和服务帐号的主要内容,如果未能解决你的问题,请参考以下文章

Google Drive API Python 服务帐户示例

具有多个用户帐户的Google Drive SDK OAuth2

Google Drive API 推送通知订阅 400“解析错误”

尝试使用 Google Drive API 的错误 JWT 签名

无需登录即可以 JSON 格式获取 Google Drive 文件夹的内容

2小时后Google Drive Python API可恢复上传错误401