Передать пользователя для олицетворения при извлечении файлов с диска

Я создал веб-приложение, в котором реализовал вход через Google. Я хочу добавить к нему функцию поиска, где пользователь может искать любой файл, присутствующий на его / ее диске. В примере кода Google Drive Api приложение открывает окно браузера, и после предоставления учетных данных токен хранится локально, и я хотел передать учетные данные через код, поэтому я создал для этого учетную запись службы.

В документации Google написано, что 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;
    }
}

В приведенном выше коде, где я могу передать идентификатор электронной почты выдающего себя за пользователя? Я использую учетные записи g-suite для своего приложения. Я попытался заменить credential = GoogleCredential.FromStream(stream).CreateScoped(Scopes); на credential = GoogleCredential.FromStream(stream).CreateScoped(Scopes).CreateWithUser("[email protected]");

Это дает исключение, говорящее

{"Ошибка:\"unauthorized_client\", Описание:\"Клиент не авторизован для получения токенов доступа с помощью этого метода.\", Uri:\"\""}


comment
Попробуйте изменить порядок CreateScoped и CreateWithUser. Я не могу объяснить, почему, но это сработало для меня.   -  person hultqvist    schedule 12.11.2019


Ответы (1)


{"Ошибка:\"unauthorized_client\", Описание:\"Клиент не авторизован для получения токенов доступа с помощью этого метода.\", Uri:\"\""}

В консоли разработчика Google вы создали проект с учетными данными. Существует два типа учетных данных, у них разные файлы и разный код, необходимый для их использования.

Код, который вы используете, предназначен для аутентификации с помощью учетной записи службы. Используемые вами файлы учетных данных, вероятно, предназначены для Oauth2. Перейдите в консоль разработчика Google, создайте другой тип учетных данных и загрузите новый файл.

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);
            }
        }
    }
person DaImTo    schedule 21.03.2018
comment
Я не понял, о чем ты говоришь Go to google developer console and create a different credential type and download the new file. - person Sonali; 21.03.2018
comment
здесь console.developers.google.com это тоже может помочь, но картинки немного устарели daimto.com/google-developer-console-service-account keycredentials.json ‹--- неправильный тип учетных данных - person DaImTo; 21.03.2018
comment
Я фактически переименовал свой файл в keycredentials.json. - person Sonali; 21.03.2018
comment
@DalmTo Я выполнил шаг, указанный здесь developers.google.com/identity/protocols/OAuth2ServiceAccount - person Sonali; 21.03.2018