Google 无需用户交互即可驱动 API 身份验证

Google Drive API authentication without user interaction

我正在寻找 Google Drive API 身份验证方案,该方案将授予服务应用程序(在服务器上)在 Drive 文件夹中创建共享文档的权限,而无需用户交互。

Google 我应该为此使用的特定身份验证方案的当前唯一名称可能足以回答这个问题。

虽然文档创建将响应用户操作,但文档不会与这些用户永久关联,我不希望要求任何用户提供 Google 帐户。相反,我希望用户能够在创建文档后通过网页上显示的 "Anyone with the link can edit" 类型 URL 访问该文档。

这旨在为多个通常匿名的人自动生成文档以进行协作,并且所有文档将存储在一个文件夹中。

这很可能是这个问题的重复:Google Drive API username + password authentication。不幸的是,接受的答案没有包含足够的信息让我找到我的方式,因为它引用的链接已经失效。

也可能与其他已经接受但答案不明确的问题重复,例如:.NET Google Docs API Authentication (without user interaction), How do I authenticate Google Calendar API v3 without user interaction?, and Drive API doc upload from a server without user interaction.

作为服务帐户进行身份验证是我需要的方法。

Google SDK 操作具有误导性。当我提供一些不正确的值时,它会退回到基于用户的身份验证(自动打开 Web 浏览器以请求交互式凭据)。我错误地将其解释为服务帐户功能是作为由特定交互用户批准并在特定交互用户上下文中批准的长期密钥或类似内容实现的。

不需要用户交互,但是需要 .p12 证书,而不是默认的 .json 文件提供的任何凭据(我曾尝试以多种方式使用)。这是我使用的代码:

using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v2;
using Google.Apis.Drive.v2.Data;
using Google.Apis.Http;
using Google.Apis.Services;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

using GData = Google.Apis.Drive.v2.Data;

public class Drive
{
    private const string GoogleDocMimeType = "application/vnd.google-apps.document";

    /// <summary>
    /// Creates a drive service, authenticated using information found in the Google Developers Console under "APIs & auth / Credentials / OAuth / Service account"
    /// </summary>
    /// <param name="svcEmail">The service account "Email address"</param>
    /// <param name="certPath">The path to the service account "P12 key" file</param>
    public Drive(string svcEmail, string certPath)
    {
        Service = AuthenticateService(svcEmail, certPath);
    }

    private DriveService Service
    {
        get;
        set;
    }

    /// <summary>
    /// Creates a "Google Doc" and shares it with anyone with the link
    /// </summary>
    /// <param name="title"></param>
    /// <returns>The drive FileId, accessible at https://docs.google.com/document/d/FileId </returns>
    public async Task<string> CreateShared(string title)
    {
        var fileId = await CreateDocument(title);
        await ShareFile(fileId);
        return fileId;
    }

    private async Task<string> CreateDocument(string title)
    {
        var file = new GData.File
        {
            Title = title,
            MimeType = GoogleDocMimeType
        };
        file = await Service.Files.Insert(file).ExecuteAsync();
        return file.Id;
    }

    private async Task ShareFile(string fileId)
    {
        Permission permission = new Permission
        {
            Type = "anyone",
            Role = "writer",
            WithLink = true
        };
        var a = Service.Permissions.Insert(permission, fileId);
        await a.ExecuteAsync();
    }

    private static DriveService AuthenticateService(string svcEmail, string certPath)
    {
        string[] scopes = new[] { DriveService.Scope.DriveFile };
        X509Certificate2 certificate = new X509Certificate2(certPath, "notasecret", X509KeyStorageFlags.Exportable);

        var init = new ServiceAccountCredential.Initializer(svcEmail) { Scopes = scopes };
        IConfigurableHttpClientInitializer credential = new ServiceAccountCredential(init.FromCertificate(certificate));

        return new DriveService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = "Document Management Service",
        });
    }
}

这是一个实验性消费者:

internal class Program
{
    private const string svcEmail = "serviceaccountid@developer.gserviceaccount.com";
    private const string certPath = @"credentials\projectname-fingerprintprefix.p12";
    private readonly static Drive drive = new Drive(svcEmail, certPath);

    private static void Main(string[] args)
    {
        string id = drive.CreateShared("my title").Result;
        Console.WriteLine(id);
    }
}

这似乎在一个孤立的 application/project-specific 数据存储库中使用 Google 驱动器存储。根据其他帖子,无法获得交互式 Drive UI 视图。我不知道它是否使用我的个人存储配额等。但是,这是我迄今为止最好的方法,接下来我将自己(不在这里)回答这些问题。