【问题标题】:Pass user to impersonate while fetching files from drive在从驱动器获取文件时传递用户以模拟
【发布时间】:2018-03-21 09:53:40
【问题描述】:

我创建了一个 Web 应用程序,并在其中实现了 google 登录。我想为其添加搜索功能,用户可以在其中搜索他/她的驱动器中存在的任何文件。在 Google Drive Api 的示例代码中,应用程序打开浏览器窗口,提供凭据后,令牌存储在本地,我想通过代码传递凭据,因此为此创建了一个服务帐户。

google documentation 中写着Your application now has the authority to make API calls as users in your domain (to "impersonate" users). When you prepare to make authorized API calls, you specify the user to impersonate.

这是我的代码-

static void Main(string[] args)
{
    try
    {
        var service = AuthenticateServiceAccountV1(GServiceAccount, "keycredentials.json");
        FilesResource.ListRequest listRequest = service.Files.List();
        listRequest.PageSize = 1000;
        listRequest.Fields = "nextPageToken, files(webViewLink, name, id)";
        IList<Google.Apis.Drive.v3.Data.File> files = listRequest.Execute().Files;
        Console.WriteLine("Processing...\n");
        if (files != null && files.Count > 0)
        {
            var listfiles = files.Select(x => x.Id).ToList();
            Console.WriteLine(files.Count + " records fetched.");
        }
        else
        {
            Console.WriteLine("No files found.");
        }
        Console.ReadLine();
    }
    catch(Exception ex)
    {
        throw ex;
    }
}

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

        if (Path.GetExtension(KeyFilePath).ToLower() == ".json")
        {
            GoogleCredential credential;
            using (var stream = new FileStream(KeyFilePath, FileMode.Open, FileAccess.Read))
            {
                credential = GoogleCredential.FromStream(stream)
                     .CreateScoped(Scopes);
            }

            return new DriveService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = ApplicationName,
            });
        }
        else if (Path.GetExtension(KeyFilePath).ToLower() == ".p12")
        {
            var certificate = new X509Certificate2(KeyFilePath, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
            ServiceAccountCredential credential = new ServiceAccountCredential(
                new ServiceAccountCredential.Initializer(ServiceAccountEmail)
                {
                    Scopes = Scopes,
                }.FromCertificate(certificate));

            return new DriveService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = ApplicationName
            });
        }
        else
        {
            throw new Exception("Unsupported Service accounts credentials.");
        }
    }
    catch (Exception ex)
    {
        return null;
    }
}

在上面的代码中,我可以在哪里传递模拟用户的电子邮件 ID?我正在为我的应用程序使用 g-suite 帐户。我试图用credential = GoogleCredential.FromStream(stream).CreateScoped(Scopes).CreateWithUser("userid@gmail.com"); 替换credential = GoogleCredential.FromStream(stream).CreateScoped(Scopes);

它给出了一个例外说

{"Error:\"unauthorized_client\", Description:\"客户端未经授权无法使用此方法检索访问令牌。\", Uri:\"\""}

【问题讨论】:

  • 尝试更改CreateScopedCreateWithUser 的顺序。我无法解释原因,但它对我有用。

标签: c# google-api google-drive-api google-api-dotnet-client google-drive-shared-drive


【解决方案1】:

{"Error:\"unauthorized_client\", Description:\"客户端未经授权无法使用此方法检索访问令牌。\", Uri:\"\""}

在 google 开发者控制台中,您使用凭据创建了一个项目。有两种类型的凭证,它们有不同的文件和不同的代码来使用它们。

您使用的代码用于使用服务帐户进行身份验证。您使用的凭证文件可能是用于 Oauth2。转到谷歌开发者控制台并创建不同的凭据类型并下载新文件。

ServiceAccount.cs

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);
            }
        }
    }

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-17
  • 2012-12-29
  • 2019-06-25
  • 1970-01-01
  • 2018-12-31
  • 2011-08-13
  • 2017-11-27
相关资源
最近更新 更多