Я пишу внутренний процесс на Java, который будет выдавать себя за пользователя и добавлять / удалять документы на их Google Диске.
Учетная запись сервера проходит аутентификацию правильно, но когда я пытаюсь выдать себя за пользователя, я получаю 401 Unauthorized error
. Детали смотрите ниже.
Конфигурация
Я настроил учетную запись сервера следующим образом:
- Создал проект под Google API и включил Google Drive API
- Создал учетную запись службы с именем [email protected], установил роль как Актер учетной записи службы и предоставил ей делегирование на уровне домена. Он имеет идентификатор клиента 110xxxxxxxxx342
- Я скачал ключевой файл P12
Я настроил домен с помощью экрана доступа клиента Manage API, чтобы разрешить 110xxxxxxxxx342 иметь область действия: https://www.googleapis.com/auth/drive.
Служба поддержки Google изучила мою конфигурацию и дала ей высокую оценку.
Тогда мой код выглядит следующим образом:
package com.dcm.sharingdocuments;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Map.Entry;
import com.google.api.client.auth.oauth2.TokenErrorResponse;
import com.google.api.client.auth.oauth2.TokenResponseException;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.FileList;
public class SharingDocumentsTest3 {
private static final String SERVICE_ACCOUNT_EMAIL = " [email protected]";
public static Drive getDriveService(String userEmail) throws Exception {
File keyFile = new File("E:\\Projects\\Workspace\\Sharing Documents\\authentication\\AnotherTestKeyFile.p12");
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
List<String> SCOPES = Arrays.asList(DriveScopes.DRIVE_METADATA_READONLY);
GoogleCredential credential = null;
if (userEmail == null) {
credential = new GoogleCredential.Builder().setTransport(httpTransport).setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL).setServiceAccountScopes(SCOPES)
.setServiceAccountPrivateKeyFromP12File(keyFile).build();
credential.refreshToken();
} else {
credential = new GoogleCredential.Builder().setTransport(httpTransport).setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL).setServiceAccountScopes(SCOPES)
.setServiceAccountPrivateKeyFromP12File(keyFile).setServiceAccountUser(userEmail).build();
credential.refreshToken();
}
Drive service = new Drive.Builder(httpTransport, jsonFactory, null).setHttpRequestInitializer(credential)
.build();
return service;
}
public static void main(String[] args) {
SharingDocumentsTest3 sdt3 = new SharingDocumentsTest3();
sdt3.execute();
}
private void execute() {
try {
Drive service = getDriveService(null);
Drive services = getDriveService("[email protected]");
displayFiles(services);
} catch (Exception e) {
e.printStackTrace();
}
}
private void displayFiles(Drive service) throws Exception {
FileList result = service.files().list().setPageSize(10).execute();
List<com.google.api.services.drive.model.File> files = result.getFiles();
if (files == null || files.size() == 0) {
System.out.println("No files found.");
} else {
System.out.println("Files:");
for (com.google.api.services.drive.model.File file : files) {
Set<Entry<String, Object>> entries = file.entrySet();
Iterator<Entry<String, Object>> it = entries.iterator();
while (it.hasNext()) {
Entry<String, Object> entry = it.next();
String key = entry.getKey();
Object value = entry.getValue();
if (value instanceof String) {
System.out.println("\tKey = " + key + ", Value = " + (String) value);
} else {
System.out.println("\tKey = " + key + ", Value = " + value.toString());
}
}
System.out.printf("%s (%s)\n", file.getName(), file.getId());
}
}
}
}
Когда я запускаю код, как указано выше, я получаю сообщение об ошибке:
Mar 29, 2017 9:55:27 AM com.google.api.client.googleapis.services.AbstractGoogleClient <init>
WARNING: Application name is not set. Call Builder#setApplicationName.
com.google.api.client.auth.oauth2.TokenResponseException: 401 Unauthorized
at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:105)
at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:287)
at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:307)
at com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:384)
at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:489)
at com.dcm.sharingdocuments.SharingDocumentsTest3.getDriveService(SharingDocumentsTest3.java:50)
at com.dcm.sharingdocuments.SharingDocumentsTest3.execute(SharingDocumentsTest3.java:75)
at com.dcm.sharingdocuments.SharingDocumentsTest3.main(SharingDocumentsTest3.java:65)
Таким образом, код не работает в credential.refreshToken (), когда я устанавливаю setServiceAccountUser. Кажется, он успешно обновил токен, но я этого не сделал. Я пробовал различные комбинации этого кода - например, закомментировал строки refreshToken (), закомментировал строку getDriveService (null), но всякий раз, когда я пытаюсь использовать / обновлять учетные данные, полученные для олицетворенного пользователя, я получаю ошибку 401 Unauthorized.
Если я изменю код так, чтобы диск, полученный с помощью getDriveService (null), был передан в DisplayFiles (...), то я получу один файл в списке под названием «Начало работы». Таким образом, похоже, что авторизация учетной записи службы работает, и Google добавил свой файл по умолчанию на Диск для учетной записи сервера.
Я использую google-*1.22.0.jar
файлы и Java 1.8
для выполнения вышеуказанного кода
Проблема, я думаю, заключается в том, как я настроил домен или как я пытаюсь выдать себя за пользователя, но мой код выглядит так же, как и многие примеры в Интернете, и служба поддержки Google, похоже, сообщает, что я правильно настроил домен.
Мы будем очень признательны за все, что вы можете предложить в качестве решения или следующего шага!