В предыдущей статье мы узнали о Guzzle и о том, как он может помочь нам в установлении связи со сторонними API через HTTP. Мы использовали его, чтобы получить выходные данные генератора случайных чисел и для базового взаимодействия с API Github. Он также предлагает серию «подписчиков», одним из которых является log-subscriber , и мы увидели, как легко интегрировать в него монолог .
Во время взаимодействия с API Github мы обнаружили, что он поддерживает базовую аутентификацию (отправка простого имени пользователя / пароля). Но что, если API, который мы хотим использовать, просто предлагает аутентификацию OAUTH ?
Гоутс оут
Внедрение OAUTH с нуля может быть трудной и трудоемкой задачей, и это все равно что заново изобретать колесо … Вы можете взять стороннюю библиотеку для обработки запросов OAUTH, но зачем делать это, когда у Guzzle есть собственный подписчик OAUTH ? Ура!
Прежде всего, я должен сообщить вам, что Guzzle прекратил поддержку PHP 5.3, поэтому вам потребуется PHP 5.4 для выполнения этого упражнения. Инструкции по установке из предыдущей статьи немного изменились, но Composer делает нашу жизнь намного проще.
Наша цель — взаимодействовать с API-интерфейсом Twitter и получать собственную временную шкалу, для которой мы всегда нуждаемся. Начнем с нашего файла composer.json:
{ "name": "johndoe/guzzle-twitter", "description": "PoC for Sitepoint article", "authors": [ { "name": "John Doe", "email": "[email protected]" } ], "minimum-stability": "dev", "require": { "guzzlehttp/guzzle": "4.*", "guzzlehttp/log-subscriber": "1.*", "monolog/monolog": "*", "guzzlehttp/oauth-subscriber": "*", } }
Обратите внимание, что мы используем Guzzle 4.x, подписчик журнала, монолог в качестве нашего сервера регистрации и, наконец, главная цель этой статьи: oauth-subscriber.
Теперь мы должны выполнить команду composer update
чтобы установить все необходимое.
Что касается кода, он очень прост:
<?php require 'vendor/autoload.php'; use GuzzleHttp\Client; use GuzzleHttp\Subscriber\Oauth\Oauth1; use GuzzleHttp\Subscriber\Log\LogSubscriber; use GuzzleHttp\Subscriber\Log\Formatter; use Monolog\Logger; use Monolog\Handler\StreamHandler; date_default_timezone_set('America/Phoenix'); //Set to a proper timezone /* * Setting up the logging backend, */ $log = new Logger('guzzle'); $log->pushHandler(new StreamHandler('guzzle.log')); // Log will be found at a file named guzzle.log $subscriber = new LogSubscriber($log, Formatter::SHORT); //To see full details, you can use Formatter::DEBUG /* * Creating the Guzzle client, we are setting oauth as the default authentication method */ $client = new Client(['base_url' => 'https://api.twitter.com', 'defaults' => ['auth' => 'oauth']]); /* * Setting up the oauth subscriber parameters. Parameter values have to be generated at the Twitter site */ $oauth = new Oauth1([ 'consumer_key' => '', 'consumer_secret' => '', 'token' => '', 'token_secret' => '' ]); /* * Attaching the oauth and the log subscriber to the client */ $client->getEmitter()->attach($oauth); $client->getEmitter()->attach($subscriber); /* * Executing a GET request on the timeline service, pass the result to the json parser */ $res = $client->get('1.1/statuses/home_timeline.json')->json(); print_r($res); //we have the parsed response in an array!
Теперь давайте посмотрим интересные строки здесь
<?php // ...... $client = new Client(['base_url' => 'https://api.twitter.com', 'defaults' => ['auth' => 'oauth']]); // ......
Конструктор объекта клиента Guzzle HTTP принимает массив, определяющий несколько параметров конфигурации. Параметр по defaults
определен в документации как «Параметры запроса по умолчанию, применяемые к каждому запросу» ( см. Код на Github ). В этом случае мы определяем, что для каждого запроса, который выполняет клиент, он должен использовать механизм авторизации OAUTH.
// ...... $oauth = new Oauth1([ 'consumer_key' => '', 'consumer_secret' => '', 'token' => '', 'token_secret' => '' ]); // ......
Затем мы создаем объект Oauth1
, содержащий параметры, необходимые для авторизации OAUTH. Необходимые значения параметров зависят от того, настроим ли мы OAUTH в режиме с 1 или 3 ножками. Вы можете увидеть эту статью для объяснения различий между этими режимами.
Основными параметрами являются consumer_key
и consumer_secret
. Twitter будет генерировать эти параметры при регистрации приложения следующим образом:
Прежде всего, перейдите на https://apps.twitter.com/ и нажмите кнопку [Создать новое приложение] . Заполните поля Имя, Описание и Веб-сайт, но пока оставьте URL-адрес обратного вызова пустым. Согласитесь с TOS и, наконец, нажмите кнопку [Создать приложение в Твиттере] .
После регистрации приложения перейдите на вкладку [Api Keys] . Вы должны увидеть коды Api Key и API Secret ; это ваши параметры consumer_key
и consumer_secret
.
OAUTH одноногий режим является наиболее простым для кодирования. Чтобы сообщить OUTH, что мы хотим использовать этот режим, мы должны предоставить параметры token
и token_secret
. Мы должны сгенерировать их в Twitter следующим образом:
Чуть ниже, где находятся ваш ключ API и секретные коды API, вы должны увидеть кнопку [Создать мои маркеры доступа] . Нажав на нее, вы увидите свой токен доступа и секретные коды токена доступа : это параметры token
и token_secret
. Теперь у вас есть все, чтобы заполнить объект Oauth1.
Чтобы наконец заставить наш код работать, нам просто нужно подключить подписчика OAUTH к клиенту Guzzle с помощью $client->getEmitter()->attach($oauth);
команда. Мы готовы выполнить наш первый запрос!
В Twitter вы можете использовать 3-хногого Oauth, внеся некоторые изменения.
Сначала мы должны создать точку входа для нашего приложения с Twitter для проверки пользователя:
<?php session_start(); require 'vendor/autoload.php'; use GuzzleHttp\Client; use GuzzleHttp\Subscriber\Oauth\Oauth1; use GuzzleHttp\Subscriber\Log\LogSubscriber; use Monolog\Logger; use Monolog\Handler\StreamHandler; use GuzzleHttp\Subscriber\Log\Formatter; date_default_timezone_set('America/Phoenix'); $log = new Logger('guzzle'); $log->pushHandler(new StreamHandler('guzzle.log')); $client = new Client(['base_url' => 'https://api.twitter.com', 'defaults' => ['auth' => 'oauth']]); $subscriber = new LogSubscriber($log, Formatter::SHORT); $client->getEmitter()->attach($subscriber); $oauth = new Oauth1([ 'consumer_key' => '[your_api_key]', 'consumer_secret' => '[your_api_secret]' ]); $client->getEmitter()->attach($oauth); // Set the "auth" request option to "oauth" to sign using oauth $res = $client->post('oauth/request_token', ['body' => ['oauth_callback' => 'http://[yourawesomehost]/callback.php']]); $params = (string)$res->getBody(); parse_str($params); $_SESSION['oauth_token'] = $oauth_token; $_SESSION['oauth_token_secret'] = $oauth_token_secret; header("Location: https://api.twitter.com/oauth/authenticate?oauth_token={$oauth_token}");
Наиболее важные части кода
// ...... $oauth = new Oauth1([ 'consumer_key' => '[your_api_key]', 'consumer_secret' => '[your_api_secret]' ]); // ......
Обратите внимание, что мы не используем параметры token
и token_secret
(пока). Вам все еще нужно сгенерировать свой ключ API и секрет API, как описано выше.
// ...... $res = $client->post('oauth/request_token', ['body' => ['oauth_callback' => 'http://[yourawesomehost]/callback.php']]); // ......
Приведенное выше заявление отправит запрос POST в oauth / request_token (это первый этап трехстороннего процесса OAUTH). В качестве параметра мы передаем требуемый URL обратного вызова, где Twitter перенаправляет пользователя после того, как он вошел в систему и предоставил разрешение нашему приложению на использование его учетной записи.
Успешный ответ будет включать 2 параметра: oauth_token
и oauth_token_secret
. Обязательно сохраните эти два значения; в приведенном выше примере они хранятся в $_SESSION
.
// ...... header("Location: https://api.twitter.com/oauth/authenticate?oauth_token={$oauth_token}"); // ......
В качестве последнего шага мы перенаправим пользователя на экран входа в Twitter. Там ему нужно будет войти в систему и предоставить нашему приложению доступ к информации его учетной записи (это второй этап). Нам нужно отправить в качестве параметра параметр oauth_token
мы получили в первом запросе.
Теперь давайте посмотрим на содержимое файла callback.php:
<?php session_start(); require 'vendor/autoload.php'; use GuzzleHttp\Client; use GuzzleHttp\Subscriber\Oauth\Oauth1; use GuzzleHttp\Subscriber\Log\LogSubscriber; use Monolog\Logger; use Monolog\Handler\StreamHandler; use GuzzleHttp\Subscriber\Log\Formatter; date_default_timezone_set('America/Phoenix'); $authToken = $_GET['oauth_token']; $authVerifier = $_GET['oauth_verifier']; $log = new Logger('guzzle'); $log->pushHandler(new StreamHandler('guzzle.log')); $client = new Client(['base_url' => 'https://api.twitter.com', 'defaults' => ['auth' => 'oauth']]); $subscriber = new LogSubscriber($log, Formatter::SHORT); $client->getEmitter()->attach($subscriber); $oauth = new Oauth1([ 'consumer_key' => '[your_api_key]', 'consumer_secret' => '[your_api_secret]', 'token' => $_SESSION['oauth_token'] ]); $client->getEmitter()->attach($oauth); if ($authToken == $_SESSION['oauth_token']) { $res = $client->post('oauth/access_token', ['body' => ['oauth_verifier' => $authVerifier]]); $params = (string)$res->getBody(); parse_str($params); $_SESSION['oauth_token'] = $oauth_token; $_SESSION['oauth_token_secret'] = $oauth_token_secret; $_SESSION['userId'] = $user_id; $_SESSION['screenName'] = $screen_name; header("Location: timeline.php"); }
Если пользователь вошел в систему и авторизовал наше приложение, Twitter перенаправит его в наш файл обратного вызова. Он предоставит два параметра: oauth_token
и oauth_verifier
. Нам нужно поймать этих двоих.
<?php // ...... $authToken = $_GET['oauth_token']; $authVerifier = $_GET['oauth_verifier']; // ......
Имейте в виду, что получение внешних параметров без предварительной фильтрации и проверки их является большой угрозой безопасности для вашего приложения . Для простоты, мы не очищаем ввод / вывод, просто убедитесь, что ВЫ ДЕЛАЕТЕ! 😉
Давайте теперь посмотрим на подписчика Guzzle’s Oauth
<?php // ...... $oauth = new Oauth1([ 'consumer_key' => '[your_api_key]', 'consumer_secret' => '[your_api_secret]', 'token' => $_SESSION['oauth_token'] ]); // ......
Теперь параметр token
снова присутствует в первом запросе.
// ...... if ($authToken == $_SESSION['oauth_token']) // ......
В целях безопасности мы должны проверить, oauth_token
параметр oauth_token
предоставленный нашему oauth_token
параметром, который мы получили в первом запросе.
А вот и третий этап:
// ...... $res = $client->post('oauth/access_token', ['body' => ['oauth_verifier' => $authVerifier]]); // ......
Мы должны отправить запрос POST в oauth/access_token
и отправить параметр oauth_verifier
полученный нами в oauth_token
oauth_token_secret
чтобы получить окончательные параметры oauth_token
и oauth_token_secret
необходимые для полного запроса OAUTH. Если запрос выполнен успешно, вместе с этими двумя параметрами мы получим другие, такие как user_id
и screen_name
. Мы можем сохранить все эти данные в сеансе, чтобы, наконец, сделать аутентифицированный OAUTH-запрос в качестве нашего 1-конечного примера:
<?php session_start(); require 'vendor/autoload.php'; use GuzzleHttp\Client; use GuzzleHttp\Subscriber\Oauth\Oauth1; use GuzzleHttp\Subscriber\Log\LogSubscriber; use GuzzleHttp\Subscriber\Log\Formatter; use Monolog\Logger; use Monolog\Handler\StreamHandler; date_default_timezone_set('America/Phoenix'); //Set to a proper timezone /* * Setting up the logging backend, */ $log = new Logger('guzzle'); $log->pushHandler(new StreamHandler('guzzle.log')); // Log will be found at a file named guzzle.log $subscriber = new LogSubscriber($log, Formatter::SHORT); //To see full details, you can use Formatter::DEBUG /* * Creating the Guzzle client, we are setting oauth as the default authentication method */ $client = new Client(['base_url' => 'https://api.twitter.com', 'defaults' => ['auth' => 'oauth']]); /* * Setting up the oauth subscriber parameters. Parameter values * have to be generated at the Twitter site */ $oauth = new Oauth1([ 'consumer_key' => '[your_api_key]', 'consumer_secret' => '[your_api_secret]', 'token' => $_SESSION['oauth_token'], 'token_secret' => $_SESSION['oauth_token_secret'] ]); /* * Attaching the oauth and the log subscriber to the client */ $client->getEmitter()->attach($oauth); $client->getEmitter()->attach($subscriber); /* * Executing a GET request on the timeline service, pass the result to the json parser */ $res = $client->get('1.1/statuses/home_timeline.json')->json(); echo '<pre>'; echo 'Timeline for user ' . $_SESSION['screenName'] . ':' . PHP_EOL . '<hr>'; foreach ($res as $tweet) { echo 'From: ' . $tweet['user']['name'] . ' (@' . $tweet['user']['screen_name'] . ')' . PHP_EOL; echo ' ' . htmlentities($tweet['text']) . PHP_EOL . '<hr>'; }
В конце мы имеем полный абонентский объект Guzzle OAUTH. Этот объект имеет параметры token
и token_secret
полученные из запроса третьей token_secret
и сохраненные в сеансе:
// ...... $oauth = new Oauth1([ 'consumer_key' => '[your_api_key]', 'consumer_secret' => '[your_api_secret]', 'token' => $_SESSION['oauth_token'], 'token_secret' => $_SESSION['oauth_token_secret'] ]); // ......
Вывод
Как вы можете видеть, Guzzle позволяет легко выполнить OAUTH-авторизацию, не беспокоясь о мрачных деталях подписания запроса. Если у вас есть какие-либо вопросы или предложения, пожалуйста, дайте мне знать в комментариях ниже. Весь исходный код для этого урока доступен на Github . Любые конструктивные отзывы всегда будут приветствоваться!