Google Диск /OAuth - не удается выяснить, как получить повторно используемые GoogleCredentials
Я успешно установил и запустил приложение быстрого запуска Google Диска под названием DriveCommandLine. Я также немного адаптировал его для получения информации о файле для одного из файлов в моей учетной записи накопителя.
Теперь я хочу сохранить учетные данные и повторно использовать их без необходимости посещать веб-страницу каждый раз, чтобы получить код авторизации. Я проверил эту страницу с инструкциями по извлечению и использованию учетных данных OAuth 2.0. Чтобы использовать класс example (MyClass), я изменил строку в DriveCommandLine, где создается экземпляр объекта Credential:
Credential credential = MyClass.getCredentials(code, "");
В результате возникает следующее исключение:
java.lang.NullPointerException
at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:187)
at com.google.api.client.json.jackson.JacksonFactory.createJsonParser(JacksonFactory.java:84)
at com.google.api.client.json.JsonFactory.fromInputStream(JsonFactory.java:247)
at com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets.load(GoogleClientSecrets.java:168)
at googledrive.MyClass.getFlow(MyClass.java:145)
at googledrive.MyClass.exchangeCode(MyClass.java:166)
at googledrive.MyClass.getCredentials(MyClass.java:239)
at googledrive.DriveCommandLine.<init>(DriveCommandLine.java:56)
at googledrive.DriveCommandLine.main(DriveCommandLine.java:115)
Я просматриваю эти API (Google Диск и OAuth) уже 2 дня и добился очень большого прогресса. Я бы очень признателен за помощь в вышеупомянутой ошибке и проблеме получения постоянных учетных данных в целом.
Вся эта структура кажется мне излишне сложной. Кто-нибудь хочет объяснить, почему я не могу просто создать простой объект Credential, передав свое имя пользователя и пароль Google?
Спасибо,
Брайан О Кэрролл, Дублин, Ирландия
* Обновление *
Хорошо, я только что обошел вышеупомянутую ошибку, и теперь у меня есть новая.
То, как я столкнулся с первой проблемой, - это изменить MyClass.getFlow(). Вместо того, чтобы создавать объект GoogleClientServices из json файла, я использовал другую версию GoogleAuthorizationCodeFlow.Builder, которая позволяет вам вводить идентификатор клиента и секрет клиента непосредственно в виде строк:
flow = new GoogleAuthorizationCodeFlow.Builder(httpTransport, jsonFactory, "<MY CLIENT ID>", "<MY CLIENT SECRET>", SCOPES).setAccessType("offline").setApprovalPrompt("force").build();
Теперь проблема заключается в том, что я получаю следующую ошибку, когда пытаюсь использовать поток (объект GoogleAuthorizationCodeFlow) для обмена авторизационным кодом для объекта Credentials:
An error occurred: com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
"error" : "invalid_scope"
}
googledrive.MyClass$CodeExchangeException
at googledrive.MyClass.exchangeCode(MyClass.java:185)
at googledrive.MyClass.getCredentials(MyClass.java:262)
at googledrive.DriveCommandLine.<init>(DriveCommandLine.java:56)
at googledrive.DriveCommandLine.main(DriveCommandLine.java:115)
Есть ли какая-то другая область, которую я должен использовать для этого? В настоящее время я использую массив областей с MyClass:
private static final List<String> SCOPES = Arrays.asList(
"https://www.googleapis.com/auth/drive.file",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile");
Спасибо!
Ответы
Ответ 1
Я чувствую твою боль. Я два месяца и все еще удивляюсь.
Некоторые из моих исследований...
-
Когда вы запрашиваете разрешения пользователя, укажите "offline = true". Это будет (иногда "sic" ) возвращает refreshtoken, что равнозначно паролю с ограниченными разрешениями. Вы можете сохранить это и повторно использовать его в любое время (пока пользователь не аннулирует его), чтобы получить токен доступа.
-
Я чувствую, что SDK Google являются скорее препятствием, чем помощью. Один за другим я прекратил их использовать и теперь напрямую вызываю REST API.
-
В последнем пункте вы можете (просто) использовать протокол Google clientlogin для доступа к API предыдущего поколения. Однако это полностью устарело и вскоре будет отключено. OAuth предназначен для мелкозернистого контроля авторизации, которая по своей сути сложна. Поэтому, хотя я согласен, что это сложно, я не думаю, что это излишне. Мы живем в сложном мире: -)
Ваши и мои опыты показывают, что сообщество разработчиков все еще нуждается в сводном документе и рецептах, чтобы получить этот материал в наши зеркала заднего вида, чтобы мы могли сосредоточиться на задаче.
Ответ 2
Oath2Scopes импортируется следующим образом:
import com.google.api.services.oauth2.Oauth2Scopes;
Для доступа к этому пакету вам необходимо предоставить файл jar 'google-api-services-oauth2-v2-rev15-1.8.0-beta.jar' в вашем классе. Его можно загрузить здесь.
Нет, я не знаю, как получить учетные данные, не посещая URL-адрес авторизации хотя бы один раз и копируя код. Я изменил MyClass, чтобы хранить и извлекать учетные данные из базы данных (в моем случае это простая таблица, содержащая userid, accesstoken и refreshtoken). Таким образом, мне нужно только получить код авторизации один раз, и как только я получу токены доступа/обновления, я могу повторно использовать их для создания объекта GoogleCredential. Здесь как Imake объект GoogleCredential:
GoogleCredential credential = new GoogleCredential.Builder().setJsonFactory(jsonFactory)
.setTransport(httpTransport).setClientSecrets(clientid, clientsecret).build();
credential.setAccessToken(accessToken);
credential.setRefreshToken(refreshToken);
Просто введите ваш clientid, clientsecret, accessToken и refreshToken выше.
У меня нет большого количества времени, чтобы отделить и убрать весь мой код, чтобы опубликовать его здесь, но если у вас все еще есть проблемы, сообщите мне, и я посмотрю, что я могу сделать. Хотя, вы действительно просите слепого за указаниями. Мое понимание всей этой системы очень отрывочно!
Cheers,
Brian
Ответ 3
Хорошо, я наконец решил вторую проблему выше, и я наконец получил рабочий объект GoogleCredential с токеном доступа и токеном обновления.
Я продолжал пытаться решить проблему с областями, изменив список областей в MyClass (тот, который управляет учетными данными). В конце концов мне нужно было настроить области видимости в моей модифицированной версии DriveCommandLine (той, которая первоначально использовалась для получения кода авторизации). Я добавил 2 области от Oauth2Scopes:
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
httpTransport, jsonFactory, CLIENT_ID, CLIENT_SECRET,
Arrays.asList(DriveScopes.DRIVE, Oauth2Scopes.USERINFO_EMAIL, Oauth2Scopes.USERINFO_PROFILE))
.setAccessType("offline").setApprovalPrompt("force").build();
Добавление областей для пользовательской информации позволило мне получить идентификатор пользователя позже в MyClass. Теперь я могу использовать идентификатор пользователя для хранения учетных данных в базе данных для повторного использования (без необходимости каждый раз обращаться к URL-адресу). Я также установил тип доступа в "автономный", как было предложено pinoyyid.