J'écris un processus dorsal en Java qui usurpera l'identité d'un utilisateur et ajouter/supprimer des documents sur leur Google Drive.401 Erreur non autorisée lors de l'utilisation d'un compte serveur pour usurper l'identité d'un utilisateur afin d'accéder à leur Google Drive
Le compte du serveur semble s'authentifier correctement mais lorsque j'essaye d'usurper l'identité d'un utilisateur, j'obtiens un 401 Unauthorized error
. S'il vous plaît voir ci-dessous pour plus de détails.
Configuration
J'ai configuré le compte du serveur comme suit:
- a créé un projet sous API Google et activé API Google Drive
- créé un compte de service appelé [email protected] .gserviceaccount.com, définissez le rôle en tant qu'Acteur de compte de service et attribuez-lui la délégation à l'échelle du domaine. Il a ID client 110xxxxxxxxx342
- je télécharger le fichier clé P12
J'ai configuré le domaine en utilisant l'écran Gérer l'accès client API pour autoriser 110xxxxxxxxx342 d'avoir la portée: https://www.googleapis.com/auth/drive.
Le service d'assistance Google a examiné ma configuration et m'a donné son feu vert.
Mon code ressemble alors comme suit:
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());
}
}
}
}
Quand je lance le code comme ci-dessus est, je reçois l'erreur:
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)
Ainsi, le code échoue à credential.refreshToken() lorsque J'ai mis le setServiceAccountUser. Il semble avoir actualisé le jeton avec succès quand je ne le fais pas. J'ai essayé différentes combinaisons de ce code - par ex. a commenté les lignes refreshToken(), a commenté la ligne getDriveService (null) - mais chaque fois que j'essaie d'utiliser/rafraîchir les informations d'identification obtenues pour l'utilisateur emprunté, j'obtiens l'erreur 401 Unauthorized.
Si je modifie le code de sorte que le lecteur obtenu par getDriveService (null) soit passé à DisplayFiles (...), je reçois un fichier appelé "Getting Started". Il semble donc que l'autorisation de compte de service fonctionne et que Google a ajouté son fichier par défaut au Drive pour le compte du serveur.
J'utilise des fichiers google-*1.22.0.jar
et Java 1.8
au terme du code ci-dessus
Le problème que je pense est la façon dont je l'ai configuré le domaine ou la façon dont je suis en train de se faire passer pour l'utilisateur, mais mon code ressemble autant Des exemples sur le Web et le support Google semblent indiquer que j'ai configuré le domaine correctement. Tout ce que vous pouvez suggérer comme une résolution ou la prochaine étape serait très appréciée!
Vérifiez la question suivante http://stackoverflow.com/questions/33602347/using-google-drive-api-from-a- Java-application où cela semble fonctionner. – Konrad
Bonjour Konrad, merci beaucoup d'avoir répondu si rapidement. J'ai examiné la question, mais le problème de l'utilisateur est résolu en supprimant setServiceAccountUser (...), sans usurper l'identité d'un utilisateur. C'est ce que je vis aussi. Le code s'exécute à condition que je n'inclue pas setServiceAccountUser (...) mais j'ai besoin d'inclure cette méthode pour emprunter l'identité d'un utilisateur et avoir accès à ses fichiers. –
1. Vous devriez laisser la bibliothèque du client s'occuper de rafraîchir votre accès. Ces comptes et services n'ont pas de jetons d'actualisation. 2. DriveScopes.DRIVE_METADATA_READONLY <- accès en lecture seule 3. démarrage rapide du compte de service https://developers.google.com/identity/protocols/OAuth2ServiceAccount – DaImTo