Создать свой API

В этой статье мы рассмотрим, что нужно, чтобы создать свой собственный three-legged OAuth server. Он позволит вам, создать, например свой собственный безопасный API, который можно распространить.

Когда работаешь с OAuth, как правило, они реализованы, как на two-legged (двуногие) или three-legged (трёхногие) OAuth server. Основное различие между ними заключается в том, что на двуногих аутентификация не связана с другим пользователем. Например, если вы хотите получить доступ к информации определенного пользователя Twitter, вам нужно использовать трёхногие сервера, так как маркер доступа должен быть получен для пользователя в вашей заявке, по сравнению с Twitter который просто предоставляет вам маркер. Мы рассмотрим three-legged, поскольку он на и более чаще используется.

Создать свой API

Выполнять тяжелую работу для нас мы заставим OAuth-PHP . Библиотека размещается на Google Code, и не перечислена в Packagist , но можно установить с помощью композитора. Для получения дополнительной информации, смотрите файл composer.json .

Понимание потока

При использовании three-legged OAuth server, типичный поток, который нам потребуется для реализации и потребления услуг, выглядит следующим образом:

Типичный поток, который разработчикам потребуется для реализации и потребления услуг
Типичный поток, который разработчикам потребуется для реализации и потребления услуг

Рисунок OAuth.net , является довольно сложным, если разобраться там показано следующее:

  • Потребительские запросы маркера с сервера
  • Затем потребитель направляет пользователя на страницу входа, передавая с ним маркер
  • Пользователь входит в систему и перенаправляется обратно к потребителю маркера доступа
  • Потребитель берет маркер доступа и просит ключ OAuth для использования в будущих безопасных запросах
  • Маркера OAuth извлекается, и разработчик может теперь сделать безопасные запросы передачи маркера для проверки

Настройка базы данных

С библиотекой OAuth PHP в доступном месте, новая база данных должна быть создана и инициализирована. Используем схему сценария поиска в library/store/mysql/mysql.sql .

Если вы просмотрели таблицу, значить видели, что таблица oauth_server_registry содержит поле с именем osr_usa_id_ref . Заполняется в процессе регистрации на сервере OAuth. И предполагает, что вы уже существующий пользователь, и будет иметь отношение к таблице. Если вы это делаете, это здорово! А если нет, то вот некоторые основные SQL запросы, чтобы создать стандартного пользователя:



CREATE TABLE users (
    id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL DEFAULT '',
    password VARCHAR(255) NOT NULL DEFAULT '',
    email VARCHAR(255) NOT NULL DEFAULT '',
    created DATE NOT NULL DEFAULT '0000-00-00',

    PRIMARY KEY (id)
);


Создание сервера OAuth

Давайте начнем писать OAuth-сервер. Следующий код является общим для остальной части нашего кода, поэтому я поместил его в отдельный файл, include/common.php :



<?php
require_once '../vendor/autoload.php';

session_start();

// Add a header indicating this is an OAuth server
header('X-XRDS-Location: http://' . $_SERVER['SERVER_NAME'] .
     '/services.xrds.php');

// Connect to database
$db = new PDO('mysql:host=localhost;dbname=oauth', 'dbuser', 'dbpassword');

// Create a new instance of OAuthStore and OAuthServer
$store = OAuthStore::instance('PDO', array('conn' => $db));
$server = new OAuthServer();


Файл добавляет дополнительный заголовок HTTP для каждого запроса информирует клиентов, что это OAuth-сервер. Обратите внимание, ссылки services.xrds.php ; этот файл с примером, который приходит с библиотекой OAuth PHP. Вы должны скопировать его из example/server/www/services.xrds.php в корневой каталог общего веб-сервера.

Следующие несколько строк кода устанавливают подключения к базе данных (информация о соединении, должна быть обновлена соответственно с вашим собственными настройками) и создаст новые экземпляры объектов OAuthStore и OAuthServer , предусмотренных в библиотеке.

Настройка для OAuth сервера завершена, и сервер готов полностью к применению. В остальных примерах, includes/common.php файл должен быть включен каждый раз для создания экземпляра сервера.

Разрешение регистрации

Прежде чем использовать сервер OAuth, нужно зарегистрироваться. Для этого нам необходимо создать простую форму регистрации. Следующие поля необходимы, потому что они передают в библиотеку: requester_name и requester_email . Остальные поля являются необязательными: application_uri и callback_uri.



<form action="register.php" method="post">
<fieldset><legend>Регистрация</legend>
<div><label for="requester_name">Логин</label>
 <input id="requester_name" type="text" name="requester_name" /></div>
<div><label for="requester_email">Email</label>
 <input id="requester_email" type="text" name="requester_email" /></div>
<div><label for="application_uri">URI</label>
 <input id="application_uri" type="text" name="application_uri" /></div>
<div><label for="callback_uri">Обратный URI</label>
 <input id="callback_uri" type="text" name="callback_uri" /></div></fieldset>
 <input type="submit" value="Зарегистрировать" /></form>


Как я упоминал ранее, библиотека предполагает, что вы существующий пользователей, который использует ваш сервер. В следующем коде, я создал нового пользователя в таблице users , и получил id , а затем передал его методом updateConsumer() для создания потребительского ключа и секрет для этого пользователя. Когда вы интегрируете это в ваше приложение, эта часть должна быть изменена, и помещена под ваш существующий процесс входа в систему, где вы уже знаете, кто этот пользователь из данных, и указан для доступа.



<?php
$stmt = $db->prepare('INSERT INTO users (name, email, created) ' .
    'VALUES (:name, :email, NOW())');
$stmt->execute(array(
    'name' => $_POST['requester_name'],
    'email' => $_POST['requester_email']
));
$id = $db->lastInsertId();

$key = $store->updateConsumer($_POST, $id, true);
$c = $store->getConsumer($key, $id);
?>
<p><strong>Сохранить свойства!</strong></p>
<p>Потребительский ключ: <strong><?=$c['consumer_key']; ?></strong></p>
<p>Потребительский секрет: <strong><?=$c['consumer_secret']; ?></strong></p>


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

Теперь, когда пользователь зарегистрирован, он может начать делать запросы на маркера доступа!

Создание маркера запроса

После того как пользователь зарегистрирован, он должен выполнить OAuth запрос к вашему файлу request_token.php . Этот файл предельно прост:



<?php
require_once 'include/oauth.php';

$server->requestToken();


Метод RequestToken() заботится о проверке того, что пользователь предоставил действительный ключ потребителя и подпись. Если запрос действителен, новый маркер запроса возвращается.

Замена маркера запроса на маркер доступа

Пользователь должен быть перенаправлен на страницу входа, что бы был только один раз сформирован маркер запроса. Для этой страницы следует нужны следующие параметры URL:oauth_token и oauth_callback .

Страница входа должна получить пользователя из таблицы пользователей. Как только он определён, идентификатор пользователя передается (наряду с oauth_token ) в метод authorizeVerify() , предусмотренный в библиотеке.

Необходимая логика основных login.php может выглядеть следующим образом:



<?php
// check if the login information is valid and get the user's ID
$sql = 'SELECT id FROM users WHERE email = :email';
$stmt = $db->prepare($sql);
$result = $stmt->exec(array(
    'email' => $_POST['requester_email']
));
$row = $result->fetch(PDO::FETCH_ASSOC);

if (!$row) {
    // incorrect login
}
$id = $row['id'];
$result->closeCursor();

// Check if there is a valid request token in the current request.
// This returns an array with the consumer key, consumer secret,
// token, token secret, and token type.
$rs = $server->authorizeVerify();
// See if the user clicked the 'allow' submit button (or whatever
// you choose)
$authorized = array_key_exists('allow', $_POST);
// Set the request token to be authorized or not authorized
// When there was a oauth_callback then this will redirect to
// the consumer
$server->authorizeFinish($authorized, $id);


После того как пользователь войдет в систему, он будут перенаправлен обратно на веб-сайт (через параметр oauth_callback ) с действительным маркером. Ключ может быть использован в обмен на действительный маркер доступа.

Основной файл access_token.php выглядит следующим образом:



<?php
require_once 'include/oauth.php';

$server->accessToken();


Этот файл также прост, как и ранее созданный request_token.php . Работа делается внутри метода accessToken() , предусмотренный библиотекой OAuth PHP. После успешного запроса, выводятся действительные oauth_token и oauth_token_secret , которые должны быть сохранены и использованы при последующих запросах к вашему API.

Проверка запроса

На данный момент, сервер OAuth запущен и работает. Но нам нужно убедиться, что запрос содержит действительной подписи OAuth. Я создан основной тестовый файл, это делает вот этот код:



<?php
require_once 'includes/oauth.php';

if (OAuthRequestVerifier::requestIsSigned()) {
    try {
        $req = new OAuthRequestVerifier();
        $id = $req->verify();
        // If we have a user ID, then login as that user (for
        // this request)
        if ($id) {
            echo 'Hello ' . $id;
        }
    }  catch (OAuthException $e)  {
        // The request was signed, but failed verification
        header('HTTP/1.1 401 Unauthorized');
        header('WWW-Authenticate: OAuth realm=""');
        header('Content-Type: text/plain; charset=utf8');
        echo $e->getMessage();
        exit();
    }
}


В примере, если запрос подтвержден, просто повторите идентификатор пользователя из пользователей, которые вошли. Можно создать повторно используя эти методы, которые содержат этот код на любые вызовы API, которые требуют безопасности.

Тестирование сервера OAuth

Наконец, пришло время, для проверки OAuth-сервера. Ниже приведен простой тестовый файл, который выполняет вышеуказанные действия:



<?php
define('OAUTH_HOST', 'http://' . $_SERVER['SERVER_NAME']);
$id = 1;

// Init the OAuthStore
$options = array(
    'consumer_key' => '<MYCONSUMERKEY>',
    'consumer_secret' => '<MYCONSUMERSECRET>',
    'server_uri' => OAUTH_HOST,
    'request_token_uri' => OAUTH_HOST . '/request_token.php',
    'authorize_uri' => OAUTH_HOST . '/login.php',
    'access_token_uri' => OAUTH_HOST . '/access_token.php'
);
OAuthStore::instance('Session', $options);

if (empty($_GET['oauth_token'])) {
    // get a request token
    $tokenResultParams = OauthRequester::requestRequestToken($options['consumer_key'], $id);

    header('Location: ' . $options['authorize_uri'] .
        '?oauth_token=' . $tokenResultParams['token'] .
        '&oauth_callback=' . urlencode('http://' .
            $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF']));
}
else {
    // get an access token
    $oauthToken = $_GET['oauth_token'];
    $tokenResultParams = $_GET;
    OAuthRequester::requestAccessToken($options['consumer_key'],
        $tokenResultParams['oauth_token'], $id, 'POST', $_GET);
    $request = new OAuthRequester(OAUTH_HOST . '/test_request.php',
        'GET', $tokenResultParams);
    $result = $request->doRequest(0);
    if ($result['code'] == 200) {
        var_dump($result['body']);
    }
    else {
        echo 'Error';
    }
}


OAuth требуются метки и подписи которые должны были быть приложены к каждому запросу, это выполняет библиотека.

В первой части кода, информация о конфигурации, которая должна быть соответственно обновлена, чтобы соответствовать вашим потребностям. id пользователя, потребительского ключа, и потребительского секрета, оба генерируются в процессе регистрации на сервере.

Как описано в three-legged OAuth server, следующий процесс выполняется в приведенном выше тестовом файле:

  • Запрос маркера (через файл request_token.php ) с потребительским ключом
  • Получив маркер, перенаправить пользователя на страницу входа передачей маркера и обратного вызова URL через параметры URL
  • После того как пользователь вошел в систему, он будут перенаправлен обратно на страницу тестов. На тестовой странице принимает маркер и просит маркер доступа (через файл access_token.php )
  • В случае успеха, необходимая информация OAuth возвращается и тестовый файл выполняет безопасный запрос test_request.php .
  • Если все пойдет хорошо слово «Hello» будет отображаться.

В заключение

На данный момент, вы должны знать, как создать базовый сервер OAuth. Использование файла test_request.php . Например, вы можете начать создавать закрепленные OAuth! Если вы хотите поиграться с кодом, смотрите полный исходный код для этой статьи . И рекомендую посмотреть пример работы OAuth .

10 комментариев на тему “Создать свой API”

  1. комментарии

    Спасибо за полезную статью обязательно буду следить за развитием

  2. комментарии

    Спасибо большое за Ваши статьи, очень полезно..

  3. комментарии

    В файле common.php есть подключающийся файл require_once '../vendor/autoload.php'; а его нет что то за файл?

  4. комментарии

    Привет Алексей,
    Хороший вопрос,
    файл autoload.php создается автоматически после загрузки необходимых вызовов композитора.

  5. комментарии

    Это просто перевод или вы проделывали это все? много не понятных моментов.

  6. комментарии

    Доброго времени суток, ищу ответ на вопрос, может быть Вы сможете прояснить.
    Нужно ли хранить access_token`ы, пользователей на сервере? Т.е. у каждого юзера хранится его текущий токен.
    Иначе, как добиться того, что бы у каждого пользователя был только один рабочий токен?

  7. комментарии

    Привет Артем,
    токены хранятся на сервере, у каждого пользователя свой id.

  8. комментарии

    Viktor, спасибо за отклик. Вопрос возник потому, что читал о том, что в OAUth нет понятия сессии, и следовательно хранить какие-либо данные об авторизации юзера на сервере не полагается.
    Я правильно понимаю, что на сервере хранится последний токен, выданный пользователю, а следовательно этот токен и является единственным валидным токеном для доступа?

  9. комментарии

    Артем, на сервере OAUTH должен вестись журнал.авторизованных пользователей. Токен выданный если возвращается маркер.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML -теги и атрибуты: <a href= http://pixelcom.crimea.ua/"" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>