Подключение к Google Compute Engine с помощью Oauth
Я пытаюсь подключиться к Google Compute Engine с помощью Java, но получаю исключение, которое для меня ничего не значит.
Пример , которому я следую, говорит следующее:
/** Authorizes the installed application to access user's protected data. */
private static Credential authorize() throws Exception {
// load client secrets
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY,
new InputStreamReader(CalendarSample.class.getResourceAsStream("/client_secrets.json")));
// set up authorization code flow
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
httpTransport, JSON_FACTORY, clientSecrets,
Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(dataStoreFactory)
.build();
// authorize
return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
}
Чтобы получить файл json, содержащий учетные данные, я иду в cloud.google.com, перейдите в мое приложение в консоли и нажмите учетные данные, я нажимаю Create new ClientId
, выберите Service Account
и JSON Key
.
При этом загружается файл _________.json
.
В public static void main(String ... args) throws Exception {
у меня есть следующий код для чтения файл учетных данных:
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY,
new FileReader("________9f.json"));
Выполнение операции System.out.println(clientSecrets);
выводит на печать весь файл json, содержащий ключи private_key_id
, client_email
, client_id
и type
.
Теперь, если я продолжу с кодом примера:
// set up authorization code flow
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
httpTransport, JSON_FACTORY, clientSecrets,
Collections.singleton(ComputeScopes.COMPUTE)).setDataStoreFactory(dataStoreFactory).build();
// authorize
new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
Это дает мне следующий stacktrace:
Исключение в потоке" main " java.яз..IllegalArgumentException at com.google.api.client.repackaged.com.google.common.base.Preconditions.checkArgument(Preconditions.java:76) около ком.гугл.прикладной программный интерфейс.клиент.утиль.Предварительное условие.checkArgument (предварительные условия.java: 37) около ком.гугл.прикладной программный интерфейс.клиент.googleapis.автор.что OAuth2.GoogleClientSecrets.getDetails (GoogleClientSecrets.Ява: 82) около ком.гугл.прикладной программный интерфейс.клиент.googleapis.автор.что OAuth2.GoogleAuthorizationCodeFlow$Builder.(GoogleAuthorizationCodeFlow.java: 195) на ком.Майси.Тестгугл.главная (TestGoogle.Ява: 52) на солнце.отражать.NativeMethodAccessorImpl.invoke0 (Native Method) at солнце.отражать.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.Ява: 57) около солнце.отражать.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java: 43) на Яве.яз..отражать.Метод.метод Invoke.java: 606) на ком.intellij.РТ.исполнения.приложение.AppMain.main (AppMain.java: 140)
Недостающие переменные (которые на данный момент являются статическими переменными) выглядят следующим образом:
JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
FileDataStoreFactory dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);
java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"), ".store/compute_engine_sample");
Я пытаюсь управлять своими экземплярами Google Compute Engine с помощью Java, любой представляешь, что я делаю не так с аутентификацией клятвы?
Обновление :
Пом.xml по запросу:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jvaas</groupId>
<artifactId>jvaas-cloud</artifactId>
<packaging>war</packaging>
<version>1.0.0</version>
<name>jVaaS Cloud</name>
<properties>
<jclouds.version>1.9.0</jclouds.version>
<project.http.version>1.19.0</project.http.version>
<project.oauth.version>1.19.0</project.oauth.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client-jackson2</artifactId>
<version>${project.http.version}</version>
</dependency>
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client-jetty</artifactId>
<version>${project.oauth.version}</version>
</dependency>
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-compute</artifactId>
<version>v1-rev27-1.19.0</version>
</dependency>
</dependencies>
</project>
TestGoogle.java в пакете по умолчанию (kots.json
находится в src/main/resources
):
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.compute.Compute;
import com.google.api.services.compute.ComputeScopes;
import com.google.api.services.compute.model.Instance;
import com.google.api.services.compute.model.InstanceList;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
public class TestGoogle {
private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"), ".store/compute_engine_sample");
private static FileDataStoreFactory dataStoreFactory;
private static HttpTransport httpTransport;
private static final String zoneName = "us-central1-a";
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static final List<String> SCOPES = Arrays.asList(ComputeScopes.COMPUTE_READONLY);
public static void main(String... args) throws Exception {
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);
InputStream in = TestGoogle.class.getResourceAsStream("/kots.json");
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
GoogleAuthorizationCodeFlow flow = // <- fails here
new GoogleAuthorizationCodeFlow.Builder(
httpTransport, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(dataStoreFactory)
.setAccessType("online").setApprovalPrompt("auto")
.build();
new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
}
}
Полный stacktrace:
Exception in thread "main" java.lang.IllegalArgumentException
at com.google.api.client.repackaged.com.google.common.base.Preconditions.checkArgument(Preconditions.java:76)
at com.google.api.client.util.Preconditions.checkArgument(Preconditions.java:37)
at com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets.getDetails(GoogleClientSecrets.java:82)
at com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow$Builder.<init>(GoogleAuthorizationCodeFlow.java:195)
at TestGoogle.main(TestGoogle.java:38)
Декомпиляция соответствующих файлов классов эти фрагменты кода связаны:
GoogleAuthorizationCodeFlow.java: 195
public Builder(HttpTransport transport, JsonFactory jsonFactory, GoogleClientSecrets clientSecrets, Collection<String> scopes) {
super(BearerToken.authorizationHeaderAccessMethod(), transport, jsonFactory, new GenericUrl("https://accounts.google.com/o/oauth2/token"), new ClientParametersAuthentication(clientSecrets.getDetails().getClientId(), clientSecrets.getDetails().getClientSecret()), clientSecrets.getDetails().getClientId(), "https://accounts.google.com/o/oauth2/auth");
this.setScopes(scopes);
}
GoogleClientSecrets.java: 82
public GoogleClientSecrets.Details getDetails() {
Preconditions.checkArgument(this.web == null != (this.installed == null));
return this.web == null?this.installed:this.web;
}
Предварительные условия.Ява: 37
public static void checkArgument(boolean expression) {
com.google.api.client.repackaged.com.google.common.base.Preconditions.checkArgument(expression);
}
Предварительные условия.java: 76
public static void checkArgument(boolean expression) {
if(!expression) {
throw new IllegalArgumentException();
}
}
Котс.json с маскировкой всех конфиденциальных данных:
{
"private_key_id": "________________________________________",
"private_key": "-----BEGIN PRIVATE KEY-----n__________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________n-----END PRIVATE KEY-----n",
"client_email": "_____________________________________________@developer.gserviceaccount.com",
"client_id": "_____________________________________________.apps.googleusercontent.com",
"type": "service_account"
}
Котс.json был сгенерирован, когда я нажал на эту кнопку в cloud.google.com
Update , кажется, мой файл json был неправильным, этот формат исправил его для меня (скопирован из разговора с @We are Borg):
{"installed": {
"client_id": "yourid",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_email": "",
"client_x509_cert_url": "",
"client_secret": "yoursecret",
"redirect_uris": ["urn:ietf:wg:oauth:2.0:oob", "http://tooltank.de"]
}}
Правильное место для загрузки - создать новый идентификатор клиента и выбрать приложение isntalled.
2 ответа:
На самом деле это не так, меня преследовали подобным образом проблемы с Google Drive, но этот код работал на меня. Я знаю, что вы подумаете, что ваш код такой же, но просто попробуйте его.
private static final List<String> SCOPES = Arrays.asList(DriveScopes.DRIVE); @Override public Credential authorize() throws IOException { InputStream in = DriveQuickstartImpl.class.getResourceAsStream("/client_secret.json"); GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in)); GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder( HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES) .setDataStoreFactory(DATA_STORE_FACTORY) .setAccessType("online").setApprovalPrompt("auto") .build(); Credential credential = new AuthorizationCodeInstalledApp( flow, new LocalServerReceiver()).authorize("user"); if(credential!=null && credential.getRefreshToken() != null){ storeCredentials(credential); } return credential; }
Если он не работает, дайте мне знать,я удалю его, мой client_secret находится в папке resources.
У меня была точно такая же проблема с оригинальным секретным файлом json, который я скачал из Google Cloud.
Все работало нормально, установив переменную env, содержащую секретный файловый путь json
set GOOGLE_APPLICATION_CREDENTIALS "secret.json path"
И запуск этой строки:
Но проблемы, подобные вашей, возникли, когда я захотел включить свой секретный файл в качестве источника ресурсов в свой проект.GoogleCredential credential = GoogleCredential.getApplicationDefault();
Таким образом, я наконец обнаружил, что эта простая строка решает проблему:
GoogleCredential credential = GoogleCredential.fromStream(MyClass.class.getResourceAsStream("/client_secrets.json"));
Надеюсь, это поможет