Google 云端硬盘 API 的文件导出端点在 API 密钥身份验证时失败?



最近Google云端硬盘API特别是导出功能是否有任何变化,这会导致它在2018年3月27日之后使用API密钥访问时失败?

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

在过去的一年里,这一直完美无缺,但在 2018 年 3 月 27 日左右突然停止工作。 从那时起,我可以检索文件详细信息;

_googleDriveHtmlContent.LoadFile(
fileId
);

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

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

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

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

使用谷歌的API资源管理器,我看到了类似的行为。

我可以使用具有get终结点的 API 资源管理器成功检索文件。 https://developers.google.com/drive/v3/reference/files/get

  • 文件标识1AIuGhzXsNuhhi0PMA1pblh0l5CCDaa1nPj8t_dasi_c
  • 身份验证:API 密钥(使用"演示 API 密钥")

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

  • 文件标识1AIuGhzXsNuhhi0PMA1pblh0l5CCDaa1nPj8t_dasi_c
  • 哑剧类型:text/html
  • 身份验证:API 密钥(使用"演示 API 密钥")

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

Google 云端硬盘 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);
}
}
}

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

授予服务帐户对文件的访问权限后,它将能够在需要时访问该文件,因此无需身份验证,因为您已通过与其共享文件对其进行了预授权。

最新更新