Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Аутентификация

Аутентификация — проверка того, кто перед нами: посетитель вводит имя и пароль, сайт находит пользователя и запоминает его в сессии. В Yii за это отвечает компонент Yii::$app->user, а сведения о пользователе даёт класс, реализующий интерфейс IdentityInterface.

Что уже есть в проекте

ФайлНазначение
models/User.phpКласс пользователя; в шаблоне проекта пользователи записаны прямо в коде
models/LoginForm.phpМодель формы входа: проверяет имя и пароль
views/site/login.phpШаблон формы входа
controllers/SiteController.phpДействия login и logout

Страница /site/login уже работает с пользователями admin и demo. Чтобы пользователи хранились в базе, достаточно заменить класс User.

Таблица пользователей

php yii migrate/create create_user_table
public function safeUp()
{
    $this->createTable('user', [
        'id' => $this->primaryKey(),
        'username' => $this->string(64)->notNull()->unique(),
        'password_hash' => $this->string(255)->notNull(),
        'auth_key' => $this->string(32)->notNull(),
    ]);
}

После php yii migrate появится таблица user. Пароль в ней хранится не открытым текстом, а хешем — необратимо преобразованной строкой.

Класс пользователя

Замените содержимое models/User.php:

// models/User.php
namespace app\models;
 
use Yii;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
 
class User extends ActiveRecord implements IdentityInterface
{
    public static function findIdentity($id)
    {
        return static::findOne($id);
    }
 
    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(string $username): ?self
    {
        return static::findOne(['username' => $username]);
    }
 
    public function validatePassword(string $password): bool
    {
        return Yii::$app->security->validatePassword($password, $this->password_hash);
    }
}

Первые пять методов требует интерфейс: по ним Yii находит пользователя по номеру из сессии и проверяет ключ «запомнить меня». Последние два вызывает готовая LoginForm. Класс пользователя указан в config/web.php: 'user' => ['identityClass' => 'app\models\User'].

Создание пользователя

$user = new User();
$user->username = 'anna';
$user->password_hash = Yii::$app->security->generatePasswordHash('secret123');
$user->auth_key = Yii::$app->security->generateRandomString();
$user->save();

Выполните этот код один раз, например во временном действии. Теперь на странице /site/login можно войти как anna с паролем secret123.

Вход и выход

Вход выполняет одна строка — она уже есть в LoginForm:

Yii::$app->user->login($user, 3600 * 24 * 30);

Второй аргумент — срок в секундах, на который пользователя запомнят после закрытия браузера. Выход — Yii::$app->user->logout().

Текущий пользователь

if (Yii::$app->user->isGuest) {
    return $this->redirect(['site/login']);
}
 
$post->user_id = Yii::$app->user->id;
$name = Yii::$app->user->identity->username;

isGuest равно true, пока посетитель не вошёл. id — номер пользователя, identity — объект User. Так при создании статьи записывают её автора.

Частая ошибка

Пароль нельзя хранить открытым текстом и сравнивать через ===: при утечке базы откроются пароли всех пользователей. Записывайте только результат generatePasswordHash() и проверяйте методом validatePassword().

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.