Если вы когда-нибудь задумывались, как устроены современные веб-сервисы, которые отдают данные мобильным приложениям или фронтенду, то ответ прост — через API. А если точнее, через RESTful API. Сегодня я расскажу, как создать такое API на Yii2, и главное — как защитить его с помощью авторизации по токенам. Это не rocket science, но есть свои подводные камни, которые мы обойдём вместе.
Что такое RESTful API и зачем он нужен
REST — это архитектурный стиль, где всё крутится вокруг ресурсов. Ресурс — это, например, пользователь, заказ или товар. Каждый ресурс имеет URL, а действия над ним выполняются через HTTP-методы: GET (получить), POST (создать), PUT (обновить), DELETE (удалить). Всё просто и логично.
Yii2 — это мощный PHP-фреймворк, который из коробки поддерживает RESTful API. Вам не нужно писать кучу кода — достаточно настроить контроллеры и правила маршрутизации. Но самое интересное — авторизация. Токен — это как ключ от квартиры. Выдал ключ — и человек может заходить. Отобрал — и доступ закрыт.
В нашем примере мы создадим API для управления списком задач (TODO). Без авторизации любой сможет читать, менять, удалять задачи. А с токенами — только те, у кого есть ключ.
Настройка окружения и базовая структура
Предположим, у вас уже есть установленный Yii2 (advanced или basic — не важно, главное, чтобы был компонент REST). Если нет — установите через Composer:
composer create-project --prefer-dist yiisoft/yii2-app-advanced api-demo
После установки перейдите в папку проекта и выполните миграции для создания таблиц пользователей. В advanced-шаблоне уже есть таблица user, но мы добавим поле для токена. Создадим миграцию:
php yii migrate/create add_token_to_user_table
В сгенерированном файле миграции добавьте поле:
public function safeUp()
{
$this->addColumn('user', 'access_token', $this->string(255)->notNull()->defaultValue(''));
}
public function safeDown()
{
$this->dropColumn('user', 'access_token');
}
Затем выполните миграцию:
php yii migrate
Теперь у нас есть поле для токена. Двигаемся дальше.
Создаём модель пользователя и проверку токена
В Yii2 авторизация по токенам реализуется через интерфейс yii\web\IdentityInterface. Наша модель User должна реализовать метод findIdentityByAccessToken(). Откройте файл common/models/User.php и добавьте следующий код:
use yii\web\IdentityInterface;
class User extends ActiveRecord implements IdentityInterface
{
// ... другие методы ...
public static function findIdentityByAccessToken($token, $type = null)
{
return static::findOne(['access_token' => $token]);
}
// Остальные методы интерфейса можно оставить как есть
}
Теперь при запросе с токеном Yii2 найдёт пользователя. Но этого мало — нужно настроить само приложение, чтобы оно принимало токен из запроса.
Конфигурируем REST API и авторизацию
В Yii2 REST API настраивается в конфигурационном файле приложения (например, api/config/main.php для advanced-шаблона). Пропишем компонент user и правила маршрутизации:
'components' => [
'user' => [
'identityClass' => 'common\models\User',
'enableAutoLogin' => false,
'enableSession' => false, // REST API не использует сессии
'loginUrl' => null, // не перенаправлять на страницу входа
],
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => 'task',
'extraPatterns' => [
'POST login' => 'login', // эндпоинт для получения токена
],
],
],
],
],
Обратите внимание на enableSession => false — это важно, потому что REST API не должен хранить состояние между запросами. Каждый запрос — как новый гость в ресторане: пришёл, поел, ушёл. Никакой памяти.
Теперь создадим контроллер для задач. В Yii2 есть готовый базовый класс yii\rest\ActiveController, который уже поддерживает все CRUD-операции. Нам нужно только переопределить поведение для авторизации:
namespace api\controllers;
use yii\rest\ActiveController;
use yii\filters\auth\HttpBearerAuth;
class TaskController extends ActiveController
{
public $modelClass = 'common\models\Task';
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => HttpBearerAuth::className(),
];
return $behaviors;
}
}
Здесь мы подключили аутентификацию через Bearer-токен. Это значит, что клиент должен передавать заголовок Authorization: Bearer <токен>. Если токен неверный или его нет — Yii2 вернёт ошибку 401.
Создаём модель Task и эндпоинт для логина
Нам нужна модель Task. Создайте её в common/models/Task.php:
namespace common\models;
use yii\db\ActiveRecord;
class Task extends ActiveRecord
{
public static function tableName()
{
return 'task';
}
public function rules()
{
return [
[['title', 'description'], 'required'],
[['title'], 'string', 'max' => 255],
[['description'], 'string'],
[['status'], 'boolean'],
];
}
}
Не забудьте создать таблицу task через миграцию:
php yii migrate/create create_task_table
Теперь добавим эндпоинт для логина. Это будет отдельный контроллер, который выдаёт токен по логину и паролю. Создадим api/controllers/AuthController.php:
namespace api\controllers;
use Yii;
use yii\rest\Controller;
use common\models\User;
use yii\web\UnauthorizedHttpException;
class AuthController extends Controller
{
public function actionLogin()
{
$request = Yii::$app->request;
$username = $request->post('username');
$password = $request->post('password');
$user = User::findByUsername($username);
if (!$user || !$user->validatePassword($password)) {
throw new UnauthorizedHttpException('Неверный логин или пароль');
}
// Генерируем токен (например, через random_bytes)
$user->access_token = bin2hex(random_bytes(32));
$user->save();
return ['access_token' => $user->access_token];
}
}
Теперь у нас есть всё для работы. Давайте протестируем.
Практический пример: как всё это работает
Представьте, что вы — мобильное приложение. Чтобы получить список задач, вы отправляете GET-запрос на /task с заголовком Authorization: Bearer <токен>. Если токен верный — сервер вернёт JSON со списком задач. Если нет — ошибку 401.
Чтобы получить токен, отправляете POST на /auth/login с логином и паролем. В ответ получите токен. Вот пример запроса через curl:
# Получаем токен
curl -X POST http://api.example.com/auth/login \
-d 'username=admin&password=123456'
# Ответ: {"access_token":"abc123..."}
# Запрос задач с токеном
curl http://api.example.com/task \
-H "Authorization: Bearer abc123..."
Всё работает. Но есть нюанс: токен хранится в базе как есть. Если базу украдут — злоумышленник получит доступ к аккаунтам. Поэтому лучше хранить хэш токена. Но это уже тема для отдельной статьи.
hash('sha256', $token)). Это защитит пользователей даже в случае утечки базы данных.
Безопасность и дополнительные советы
Авторизация по токенам — это хорошо, но есть ещё несколько моментов, о которых стоит помнить:
- Используйте HTTPS. Токен передаётся в заголовке, и если соединение не защищено, его можно перехватить.
- Устанавливайте срок действия токена. Например, через 30 дней токен становится недействительным, и пользователь должен заново пройти аутентификацию.
- Ограничьте количество попыток входа (rate limiting). Yii2 имеет встроенный фильтр
yii\filters\RateLimiter— обязательно используйте. - Для критических операций (удаление, изменение) проверяйте права доступа (RBAC).
Вот как добавить rate limiter в контроллер:
use yii\filters\RateLimiter;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['rateLimiter'] = [
'class' => RateLimiter::className(),
'enableRateLimitHeaders' => true,
];
return $behaviors;
}
Что в итоге
Мы создали RESTful API на Yii2 с авторизацией по токенам. Всё оказалось не так страшно, как казалось. Главные шаги:
- Добавили поле access_token в таблицу user.
- Реализовали
findIdentityByAccessToken()в модели User. - Настроили компонент user и urlManager для REST.
- Создали контроллер Task с аутентификацией через Bearer-токен.
- Добавили эндпоинт для логина.
Теперь вы можете расширять это API, добавлять новые ресурсы и методы. Главное — не забывайте про безопасность и тестирование. Удачи в кодинге!
Студия WNDER


