Nano Hash - криптовалюты, майнинг, программирование

Как войти в Google API в серверном приложении и использовать Google Plus?

Первоначальная задача была такой простой: получить последний пост со страницы Google+.

Потребовалось 3 дня, чтобы выяснить, что все примеры в Интернете кажутся либо устаревшими, либо неправильными, либо недействительными. Документы для разработчиков Google также не очень помогают, все больше и больше усложняя ситуацию с каждой новой запутанной страницей документации. Итак, ребята, я сдаюсь.

Сначала я попытался реализовать процедуру OAuth 2.0, которая была задокументирована в их документации (https://developers.google.com/identity/protocols/OAuth2WebServer). Как следует из названия, речь идет именно о подключении из серверного приложения. Я последовал за ним, и, на первый взгляд, это сработало: я получил ответный звонок, успешно прошел аутентификацию, получил токен доступа, сохранил его и сделал простой вызов для получения сообщений.

// Initialization

$this->googleClient = new Google_Client();
$this->googleClient->setAuthConfig(Json::decode($config->get('client_json')));
$this->googleClient->setAccessType('offline');
$this->googleClient->setIncludeGrantedScopes(TRUE);
$this->googleClient->addScope('https://www.googleapis.com/auth/plus.me');
$this->googleClient->setRedirectUri(Url::fromRoute('mymodule.gplus.callback')->setAbsolute()->toString());

// The callback

$client->authenticate($code);
$accessToken = $client->getAccessToken();

(Единственное, что здесь показалось глупым, — это область действия. Я понятия не имел, на какую область мне претендовать, если мне нужно просто прочитать общедоступный пост с общедоступной страницы, поэтому я просто выбрал первую случайную запись, которая выглядела связанной.)

Как я уже сказал, я получил токен и мог получать свои сообщения:

// Using Google_Service_Plus

$this->client()->setAccessToken($access_token);
$this->googleServicePlus = new Google_Service_Plus($this->client($reset));
$this->googleServicePlus->activities->listActivities($endpoint, 'public', ['maxResults' => 1]);

Но через 1 час он просто перестал работать, утверждая, что токен устарел или что-то в этом роде, и его нужно обновить. И вот тут наступает проблема: я не нашел способа обновить токен. $response из authenticate() больше не возвращает токен обновления (хотя он много раз упоминался в других ответах), поэтому у меня даже нет возможности его обновить.

Я попытался покопаться в библиотеке (из моего composer.json: "google/apiclient": "^2.0") и понял, что метод authenticate() на самом деле устарел, есть несколько других методов, которые, похоже, играют с токенами. Я попробовал \Google_Client::fetchAccessTokenWithAssertion(), который запросил некоторые учетные данные приложения по умолчанию... что приводит нас к совершенно другой теме и способу аутентификации, описанному здесь: https://developers.google.com/identity

Так стоит ли мне отказаться от всего, что я делал, и теперь внедрять что-то новое? Как я мог просто выполнить эту простую задачу получения новостей?

Извините за длинный вопрос.


Ответы:


1

Процесс, которому вы следуете, хорош. Проблема, с которой вы столкнулись, заключается в обновлении токена. Хотя в официальной документации указано:

Если вы используете клиентскую библиотеку API Google, объект клиента обновляет токен доступа по мере необходимости, пока вы настраиваете этот объект для автономного доступа.

Он не объясняет, как это сделать с помощью клиентской библиотеки PHP. Это было проблемой и для меня, поэтому я использую этот подход, и, надеюсь, он может помочь вам.

// 1. Build the client object
$client = new Google_Client(); 
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/index.php');
$client->setAuthConfig("client_secret.json");
$client->addScope($scopes);
$client->setAccessType("offline");

Обычно я сохраняю токен доступа в сеансе, поэтому, прежде чем продолжить, я проверяю, сохранен ли уже токен доступа в сеансе. Если это так, я продолжаю проверять, не истек ли срок действия токена доступа. Если да, то я обновляю токен доступа, а затем выполняю вызов API.

// 2. Check if the access token is already saved to session
if( isset($_SESSION["access_token"]) && ($_SESSION["access_token"]) ) {

    //set access token before checking if already expired
    $client->setAccessToken($_SESSION["access_token"]); 

    //check if access token is already expired and refresh if so
    if ($client->isAccessTokenExpired()) { 
        $refreshToken = $_COOKIE["refresh_token"]; //get refresh token
        $client->refreshToken($refreshToken); // refresh the access token
    }

    //get new access token and save it to session
    $_SESSION['access_token'] = $client->getAccessToken(); 

    // set access token after checking if already expired
    $client->setAccessToken($_SESSION["access_token"]); 

    $plusService = new Google_Service_Plus($client);  

    $optParams = array(
        "maxResults" => 5,
        "pageToken" => null
    );

    $activitiesList = $plusService->activities->listActivities("+cnn", "public", $optParams);

    $activities = $activitiesList->getItems();

    foreach ($activities as $activity ) {
        print_r($activity);
        print "<br>**********************<br>";
    }


}

Если токен доступа не сохраняется в сеансе, это означает, что аутентификация и авторизация не происходили, поэтому я приступаю к аутентификации пользователя.

// 3. Authenticate user since access token is not saved to session
else {

  if( !isset($_GET["code"]) ){ //get authorization code 

    $authUrl = $client->createAuthUrl();
    header('Location: ' . filter_var($authUrl, FILTER_SANITIZE_URL));

  } else { //exchange authorization code for access token

    $client->authenticate($_GET['code']); //authenticate client

    //get access token and save it to session
    $_SESSION['access_token'] = $client->getAccessToken();

    //save refresh token to a Cookie
    $refreshToken = $_SESSION["access_token"]["refresh_token"];
    setcookie("refresh_token", $refreshToken, time() + (86400 * 30), "/");

    $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/index.php';
    header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));

  }

}

Обратите внимание: в демонстрационных целях я сохраняю токен обновления в файле cookie в этом примере; Однако хорошо известно, что эту информацию следует сохранять не в файле cookie, а в защищенной базе данных. Кроме того, метод authenticate() не устарел, это просто псевдоним для метода fetchAccessTokenWithAuthCode(). Другое дело, что область действия, которую вы используете, не является глупой, поскольку вы получаете информацию с общедоступной страницы, согласно документации здесь и здесь, я интуитивно понял, что должен разрешить доступ только к Знай, кто ты в Google https://www.googleapis.com/auth/plus.me.

02.08.2017
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..