Google Drive API的文件导出端点是否因API密钥身份验证失败?

时间:2018-03-31 21:43:42

标签: google-api google-drive-api google-oauth google-docs-api google-api-explorer

最近使用 Google Drive API 进行了更改,特别是导出功能,这会导致在27-Mar之后使用API​​密钥访问时失败-2018?

我有一个Windows服务,可以为教育组创建和发送每日课程电子邮件。每封电子邮件的来源内容都存储在Google云端硬盘中,作为Google文档,以便教师可以轻松更新课程内容。

过去一年,这种情况一直运作良好,但在2018年3月27日左右突然停止工作。从那时起,我可以检索文件的详细信息;

    _googleDriveHtmlContent.LoadFile(
        fileId
        );

但不是内容。当我Export将文件作为HTML时,我立即从DownloadStatus.Failed处理程序中获取ProgressChanged;

    var request = _driveService.Files.Export(
        fileId, 
        "text/html"
        );

我使用API​​密钥来保证安全性,而不是OAuth,因为它是一种无UI服务。为此,我需要将文件夹标记为可公开访问 - 特别是我使用"通过链接访问每个人。"这一直很有效。

我已通过NuGet更新到最新的API v3库,但行为没有变化。

使用Google的API资源管理器,我发现了类似的行为。

我可以使用带有get端点的API Explorer成功检索我的文件。 https://developers.google.com/drive/v3/reference/files/get

  • fileId 1AIuGhzXsNuhhi0PMA1pblh0l5CCDaa1nPj8t_dasi_c
  • 身份验证:API密钥(使用"演示API密钥")

但是使用export端点,我得到内部错误(500) - https://developers.google.com/drive/v3/reference/files/export

  • fileId 1AIuGhzXsNuhhi0PMA1pblh0l5CCDaa1nPj8t_dasi_c
  • mimeType:text/html
  • 身份验证:API密钥(使用"演示API密钥")

将API Explorer中的身份验证更改为OAuth 2.0并批准访问权限,然后使用文件HTML返回成功的200结果。但是我无法做到这一点,因为我通过无UI服务访问API。

1 个答案:

答案 0 :(得分:1)

  

最近有哪些更改使用Google Drive API,特别是导出功能,这会导致在2018年3月27日之后使用API​​密钥访问时失败?

它可能但最有可能是隐形改变,你不会得到任何官方消息。不久前,我看到有人发布了类似的问题,他们使用API​​密钥更新Google表格,但它突然停止工作。

IMO如果谷歌改变了它可能是一件好事。 API密钥用于访问公共数据。将文档设置为公共文件是一个非常糟糕的主意,如果有人设法找到文档的文件ID,那么他们就可以更新文档。

建议:

您应该使用的是服务帐户。服务帐户是虚拟用户,可以在Google开发者控制台上创建服务帐户凭据,然后获取服务帐户电子邮件地址,您可以使用服务帐户在Google云端硬盘上共享文件,授予其访问所述文件的权限,而无需将文件公开。

你没有指定你正在使用的语言,但你说你正在制作一个Windows服务,所以我假设你正在使用.net。以下是使用Google .net客户端库进行服务帐户验证的示例。

 public static DriveService AuthenticateServiceAccount(string serviceAccountEmail, string serviceAccountCredentialFilePath, string[] scopes)
    {
        try
        {
            if (string.IsNullOrEmpty(serviceAccountCredentialFilePath))
                throw new Exception("Path to the service account credentials file is required.");
            if (!File.Exists(serviceAccountCredentialFilePath))
                throw new Exception("The service account credentials file does not exist at: " + serviceAccountCredentialFilePath);
            if (string.IsNullOrEmpty(serviceAccountEmail))
                throw new Exception("ServiceAccountEmail is required.");                

            // For Json file
            if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".json")
            {
                GoogleCredential credential;
                using (var stream = new FileStream(serviceAccountCredentialFilePath, FileMode.Open, FileAccess.Read))
                {
                    credential = GoogleCredential.FromStream(stream)
                         .CreateScoped(scopes);
                }

                // Create the  Analytics service.
                return new DriveService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Drive Service account Authentication Sample",
                });
            }
            else if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".p12")
            {   // If its a P12 file

                var certificate = new X509Certificate2(serviceAccountCredentialFilePath, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
                var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
                {
                    Scopes = scopes
                }.FromCertificate(certificate));

                // Create the  Drive service.
                return new DriveService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Drive Authentication Sample",
                });
            }
            else
            {
                throw new Exception("Unsupported Service accounts credentials.");
            }

        }
        catch (Exception ex)
        {                
            throw new Exception("CreateServiceAccountDriveFailed", ex);
        }
    }
}

代码从serviceaccount.cs中删除。假设您已经在使用Google .net客户端库,此方法返回的服务将与您使用api密钥时使用的驱动服务相同。

一旦您授予您的服务帐户访问该文件的权限,它就能够在需要时访问该文件,因为您需要通过与其共享文件来预先授权该文件。