Google 驱动器 API 的文件导出端点因 API 密钥验证失败?
Google Drive API's file Export endpoint is failing with API Key authentication?
Google 驱动器 APIs 最近有什么变化吗,特别是 Export 函数,这会导致它在 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-less 服务。为此,我需要将文件夹标记为可公开访问 - 特别是我正在使用 "Accessible to everyone, with link." 这一直很好用。
我已经通过 NuGet 更新到最新的 API v3 库,行为没有变化。
使用 Google 的 API 资源管理器,我看到了类似的行为。
我可以使用带有 get
端点的 API 资源管理器成功检索我的文件。
https://developers.google.com/drive/v3/reference/files/get
- 文件编号
1AIuGhzXsNuhhi0PMA1pblh0l5CCDaa1nPj8t_dasi_c
- 身份验证:API 密钥(使用 "demo API key")
但是对于 export
端点,我得到一个 内部错误 (500)-
https://developers.google.com/drive/v3/reference/files/export
- 文件编号
1AIuGhzXsNuhhi0PMA1pblh0l5CCDaa1nPj8t_dasi_c
- mime 类型:
text/html
- 身份验证:API 密钥(使用 "demo API key")
将 API Explorer 中的身份验证更改为 OAuth 2.0,并批准访问,然后 returns 文件 HTML 的成功 200 结果。但是我无法这样做,因为我正在通过 UI-less 服务访问 API。
Has anything changed recently with the Google Drive APIs and specifically the Export function, which would cause it to fail while using API Key access after 27-Mar-2018?
有可能,但很可能是秘密更改,您不会得到任何官方消息。不久前,我看到有人发布了一个类似的问题,他们正在使用 API 键来更新 Google sheet,但它突然停止工作了。
IMO 如果 google 改变了这可能是一件好事。 API 键用于访问 public 数据。将文档设置为 public 是一个非常糟糕的主意,如果有人设法找到您文档的文件 ID,他们就可以更新您的文档。
建议:
您应该使用的是服务帐户。服务帐户是虚拟用户,方法是在 Google 开发人员控制台上创建服务帐户凭据,然后获取服务帐户电子邮件地址,您可以在 Google 驱动器上共享文件,服务帐户授予它访问所述文件的权限,而无需需要制作文件 public。
您没有指定您使用的语言,但您说您正在制作 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 客户端库,此方法 returns 的服务将与您使用 api 键使用的驱动器服务相同。
一旦您授予您的服务帐户访问该文件的权限,它将能够在需要时访问该文件,因为您已经通过与其共享文件对其进行了预授权,因此无需身份验证。
Google 驱动器 APIs 最近有什么变化吗,特别是 Export 函数,这会导致它在 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-less 服务。为此,我需要将文件夹标记为可公开访问 - 特别是我正在使用 "Accessible to everyone, with link." 这一直很好用。
我已经通过 NuGet 更新到最新的 API v3 库,行为没有变化。
使用 Google 的 API 资源管理器,我看到了类似的行为。
我可以使用带有 get
端点的 API 资源管理器成功检索我的文件。
https://developers.google.com/drive/v3/reference/files/get
- 文件编号
1AIuGhzXsNuhhi0PMA1pblh0l5CCDaa1nPj8t_dasi_c
- 身份验证:API 密钥(使用 "demo API key")
但是对于 export
端点,我得到一个 内部错误 (500)-
https://developers.google.com/drive/v3/reference/files/export
- 文件编号
1AIuGhzXsNuhhi0PMA1pblh0l5CCDaa1nPj8t_dasi_c
- mime 类型:
text/html
- 身份验证:API 密钥(使用 "demo API key")
将 API Explorer 中的身份验证更改为 OAuth 2.0,并批准访问,然后 returns 文件 HTML 的成功 200 结果。但是我无法这样做,因为我正在通过 UI-less 服务访问 API。
Has anything changed recently with the Google Drive APIs and specifically the Export function, which would cause it to fail while using API Key access after 27-Mar-2018?
有可能,但很可能是秘密更改,您不会得到任何官方消息。不久前,我看到有人发布了一个类似的问题,他们正在使用 API 键来更新 Google sheet,但它突然停止工作了。
IMO 如果 google 改变了这可能是一件好事。 API 键用于访问 public 数据。将文档设置为 public 是一个非常糟糕的主意,如果有人设法找到您文档的文件 ID,他们就可以更新您的文档。
建议:
您应该使用的是服务帐户。服务帐户是虚拟用户,方法是在 Google 开发人员控制台上创建服务帐户凭据,然后获取服务帐户电子邮件地址,您可以在 Google 驱动器上共享文件,服务帐户授予它访问所述文件的权限,而无需需要制作文件 public。
您没有指定您使用的语言,但您说您正在制作 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 客户端库,此方法 returns 的服务将与您使用 api 键使用的驱动器服务相同。
一旦您授予您的服务帐户访问该文件的权限,它将能够在需要时访问该文件,因为您已经通过与其共享文件对其进行了预授权,因此无需身份验证。