Аутентификация пользователей в Yii2: пошаговая инструкция
К концу вы получите рабочую форму входа на Yii2: пользователь вводит логин и пароль, система проверяет их и запоминает сессию. Уйдёт около часа, если проект уже развёрнут.

К концу этой инструкции у вас будет форма входа на Yii2: пользователь вводит логин и пароль, приложение проверяет их по базе, запоминает сессию и пускает в закрытый раздел. Уйдёт примерно час, если каркас проекта уже развёрнут и подключён к базе. Всё описано для Yii2 (ветка 2.0.x) — это актуальная стабильная линейка фреймворка; Yii3 устроен иначе, и код отсюда там не заработает.
Yii2 из коробки даёт готовый механизм: компонент user, интерфейс IdentityInterface и класс LoginForm. Не нужно писать проверку сессий вручную — достаточно правильно соединить эти части.
Что нужно иметь до начала
Проверьте это до первой команды, чтобы не упереться в нехватку прав на пятом шаге:
- PHP 7.4 или новее (Yii2 работает и на PHP 8.x);
- установленный Composer;
- развёрнутый проект на одном из шаблонов Yii2 —
basicилиadvanced. Эта инструкция написана под шаблон basic, где всё лежит в одном приложении; - настроенное подключение к базе в
config/db.php(для basic-шаблона); - доступ к консоли для запуска миграций (
php yii).
Если вы на advanced-шаблоне, там уже есть готовая модель common\models\User и аутентификация из коробки — тогда эта инструкция вам нужна скорее как разбор того, что уже работает.
Шаг 1. Таблица пользователей
Создайте миграцию для таблицы, где будут храниться логины и хеши паролей:
php yii migrate/create create_user_table
В созданном файле миграции (папка migrations/) опишите структуру:
<?php
use yii\db\Migration;
class m240101_120000_create_user_table extends Migration
{
public function safeUp()
{
$this->createTable('{{%user}}', [
'id' => $this->primaryKey(),
'username' => $this->string()->notNull()->unique(),
'password_hash' => $this->string()->notNull(),
'auth_key' => $this->string(32)->notNull(),
'created_at' => $this->integer()->notNull(),
]);
}
public function safeDown()
{
$this->dropTable('{{%user}}');
}
}
Поле auth_key нужно для проверки «запомнить меня» — без него cookie-аутентификация работать не будет. Примените миграцию:
php yii migrate
Проверка: в консоли появится строка вроде *** applied m240101_120000_create_user_table (time: 0.05s), а в базе — таблица user с пятью полями.
Шаг 2. Модель User с IdentityInterface
Компонент user в Yii не знает, откуда брать данные о пользователе. Он общается с вашей моделью через интерфейс IdentityInterface — пять методов, которые обязательно реализовать. Создайте файл models/User.php:
<?php
namespace app\models;
use Yii;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
class User extends ActiveRecord implements IdentityInterface
{
public static function tableName()
{
return '{{%user}}';
}
// Найти пользователя по id — вызывается при восстановлении сессии
public static function findIdentity($id)
{
return static::findOne($id);
}
// Нужен только для аутентификации по токену (REST). Для формы входа не используется
public static function findIdentityByAccessToken($token, $type = null)
{
return null;
}
public function getId()
{
return $this->id;
}
public function getAuthKey()
{
return $this->auth_key;
}
public function validateAuthKey($authKey)
{
return $this->auth_key === $authKey;
}
// Поиск по логину — понадобится в форме входа
public static function findByUsername($username)
{
return static::findOne(['username' => $username]);
}
// Проверка пароля через встроенный хешер Yii
public function validatePassword($password)
{
return Yii::$app->security->validatePassword($password, $this->password_hash);
}
}
Обратите внимание: validatePassword использует Yii::$app->security — встроенный компонент, который под капотом работает через password_hash/password_verify PHP. Хранить пароли открытым текстом или через md5 нельзя.
Шаг 3. Настройка компонента user
Откройте config/web.php и убедитесь, что в секции components компонент user указывает на вашу модель:
'user' => [
'identityClass' => 'app\models\User',
'enableAutoLogin' => true,
],
Параметр enableAutoLogin включает «запомнить меня» через cookie. Именно ради него мы завели поле auth_key на шаге 1.
Шаг 4. Форма входа
В шаблоне basic уже есть класс models/LoginForm.php. Если его нет или вы хотите понять, что там происходит — вот рабочая версия:
<?php
namespace app\models;
use Yii;
use yii\base\Model;
class LoginForm extends Model
{
public $username;
public $password;
public $rememberMe = true;
private $_user = false;
public function rules()
{
return [
[['username', 'password'], 'required'],
['rememberMe', 'boolean'],
['password', 'validatePassword'],
];
}
// Валидатор: проверяет пароль, если логин найден
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
if (!$user || !$user->validatePassword($this->password)) {
$this->addError($attribute, 'Неверный логин или пароль.');
}
}
}
public function login()
{
if ($this->validate()) {
return Yii::$app->user->login(
$this->getUser(),
$this->rememberMe ? 3600 * 24 * 30 : 0
);
}
return false;
}
public function getUser()
{
if ($this->_user === false) {
$this->_user = User::findByUsername($this->username);
}
return $this->_user;
}
}
Сообщение об ошибке пишите одинаковым и для неверного логина, и для неверного пароля — «Неверный логин или пароль». Если различать эти случаи, вы подскажете чужому человеку, какой логин существует в системе.
Второй аргумент Yii::$app->user->login() — время жизни cookie в секундах. Здесь 30 дней при отмеченном «запомнить меня», иначе 0 — сессия до закрытия браузера.
Шаг 5. Экшены login и logout
В controllers/SiteController.php добавьте (в стандартном basic-шаблоне они уже есть):
use app\models\LoginForm;
use Yii;
public function actionLogin()
{
if (!Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
return $this->goBack();
}
$model->password = ''; // не отдаём пароль обратно в форму
return $this->render('login', ['model' => $model]);
}
public function actionLogout()
{
Yii::$app->user->logout();
return $this->goHome();
}
Проверка: откройте /index.php?r=site/login. Должна отрисоваться форма из views/site/login.php (в basic-шаблоне она есть по умолчанию).
Шаг 6. Создание тестового пользователя
В базе пока нет ни одной записи. Самый быстрый способ на этапе разработки — консольная команда. Создайте commands/UserController.php:
<?php
namespace app\commands;
use Yii;
use yii\console\Controller;
use app\models\User;
class UserController extends Controller
{
public function actionCreate($username, $password)
{
$user = new User();
$user->username = $username;
$user->password_hash = Yii::$app->security->generatePasswordHash($password);
$user->auth_key = Yii::$app->security->generateRandomString();
$user->created_at = time();
if ($user->save()) {
$this->stdout("Пользователь {$username} создан\n");
} else {
$this->stdout("Ошибка: " . print_r($user->errors, true) . "\n");
}
}
}
Запустите:
php yii user/create admin secret123
Проверка: в консоли — «Пользователь admin создан». В базе в таблице user появилась строка, где password_hash — длинная строка вида $2y$13$..., а не сам пароль.
Шаг 7. Закрытие раздела для гостей
Логин без защищённой страницы бессмысленен. Ограничьте доступ через AccessControl в поведениях контроллера:
use yii\filters\AccessControl;
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'only' => ['profile', 'logout'],
'rules' => [
[
'actions' => ['profile', 'logout'],
'allow' => true,
'roles' => ['@'], // только авторизованные
],
],
],
];
}
Символ @ означает «любой залогиненный пользователь», ? — гость. Теперь гость, зайдя на profile, будет переброшен на форму входа.
Проверка: выйдите из аккаунта и попробуйте открыть защищённый экшен — вас перенаправит на site/login. После входа goBack() вернёт вас обратно.
Если не получилось
- «Class 'app\models\User' does not exist» или похожая ошибка автозагрузки — проверьте
namespaceв файле модели и путь. Namespace должен соответствовать пути:app\models→models/User.php. - Форма отправляется, но всегда «Неверный логин или пароль» — скорее всего пароль в базе сохранён не через
generatePasswordHash. Проверьте, что в полеpassword_hashлежит хеш вида$2y$..., а не открытый текст. - «Setting unknown property: yii\web\User::identityClass» — вы поставили компонент
userне в ту секцию конфига или опечатались в ключе. Он должен быть внутриcomponents. - После входа сразу выбрасывает как гостя — часто причина в отсутствии или пустом
auth_keyприenableAutoLogin = true. Убедитесь, чтоgenerateRandomString()заполняет это поле при создании пользователя. - «Unable to verify your data submission» при отправке формы — не отключайте CSRF без причины. Проверьте, что в шаблоне формы используется
ActiveForm, который сам добавляет скрытое поле с токеном.
Что делать дальше
Рабочий вход есть. Дальше по порядку приоритетов:
- добавить регистрацию — отдельная форма и экшен по образцу
LoginForm, только с сохранением нового пользователя; - прикрутить восстановление пароля через email-токен — заведите поле для токена сброса и срок его жизни;
- настроить RBAC, если ролей больше одной:
authManagerв конфиге и назначение ролей вместо простой проверки@. Разграничение прав по ролям — отдельная тема, здесь мы закрыли только вход и логаут; - для API-эндпоинтов реализовать
findIdentityByAccessTokenиHttpBearerAuth— сейчас этот метод возвращаетnull.
Точные сигнатуры методов и доступные фильтры сверяйте с официальным руководством по разделу Security для вашей минорной версии 2.0.x — API компонентов между минорными релизами стабилен, но новые опции добавляются.
Логотип и фирменный стиль: Три концепции разного характера, палитра с обоснованием, проверка на читаемость в малом размере и в один цвет.
Спросить за 60 ₽Источники: Yii2 Guide — Authentication (yiiframework.com), Yii2 Guide — Authorization (Access Control Filter)
Частые вопросы
У меня advanced-шаблон, а не basic. Код подойдёт?
Работает ли эта инструкция на Yii3?
Форма отправляется, но пользователь не логинится — с чего начать?
Обязательно ли поле auth_key, если «запомнить меня» мне не нужно?
Насколько безопасно хранить пароли через Yii::$app->security?
Можно ли отключить CSRF, если форма выдаёт ошибку проверки?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.