User authentication is a fundamental feature in web applications to verify user identities. Yii2 provides a built-in authentication system using identity classes, login forms, and session-based authentication. In this tutorial, we will cover:
yii\web\UserYii2 uses the User component and an identity class that implements IdentityInterface to handle authentication. By default, Yii2 provides a User model in the common\models\User for advanced templates or app\models\User for basic templates.
If you don’t already have a user table, create one with the following structure:
CREATE TABLE `user` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(255) NOT NULL,
`email` VARCHAR(255) NOT NULL UNIQUE,
`password_hash` VARCHAR(255) NOT NULL,
`auth_key` VARCHAR(32) NOT NULL,
`access_token` VARCHAR(255) DEFAULT NULL,
`status` TINYINT(1) NOT NULL DEFAULT 1,
`created_at` INT NOT NULL,
`updated_at` INT NOT NULL
);User.php)Modify your User model to implement IdentityInterface:
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';
}
public static function findIdentity($id)
{
return static::findOne($id);
}
public static function findIdentityByAccessToken($token, $type = null)
{
return static::findOne(['access_token' => $token]);
}
public static function findByUsername($username)
{
return static::findOne(['username' => $username]);
}
public function getId()
{
return $this->id;
}
public function getAuthKey()
{
return $this->auth_key;
}
public function validateAuthKey($authKey)
{
return $this->auth_key === $authKey;
}
public function validatePassword($password)
{
return Yii::$app->security->validatePassword($password, $this->password_hash);
}
public function setPassword($password)
{
$this->password_hash = Yii::$app->security->generatePasswordHash($password);
}
public function generateAuthKey()
{
$this->auth_key = Yii::$app->security->generateRandomString();
}
}LoginForm.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, 'Incorrect username or password.');
}
}
}
public function login()
{
if ($this->validate()) {
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);
}
return false;
}
protected function getUser()
{
if ($this->_user === false) {
$this->_user = User::findByUsername($this->username);
}
return $this->_user;
}
}Modify your SiteController.php:
namespace app\controllers;
use Yii;
use yii\web\Controller;
use yii\filters\AccessControl;
use app\models\LoginForm;
class SiteController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'only' => ['logout'],
'rules' => [
[
'actions' => ['logout'],
'allow' => true,
'roles' => ['@'],
],
],
],
];
}
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();
}
return $this->render('login', ['model' => $model]);
}
public function actionLogout()
{
Yii::$app->user->logout();
return $this->goHome();
}
}views/site/login.php)use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
$this->title = 'Login';
?>
<div class="site-login">
<h1><?= Html::encode($this->title) ?></h1>
<?php $form = ActiveForm::begin(['id' => 'login-form']); ?>
<?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<?= $form->field($model, 'rememberMe')->checkbox() ?>
<div class="form-group">
<?= Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>To restrict pages to authenticated users, modify the controllers/SiteController.php file:
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'only' => ['dashboard'],
'rules' => [
[
'actions' => ['dashboard'],
'allow' => true,
'roles' => ['@'], // Only authenticated users
],
],
],
];
}To protect entire controllers, add AccessControl to behaviors():
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'rules' => [
[
'allow' => true,
'roles' => ['@'],
],
],
],
];
}To hash passwords securely when creating users:
$user = new User();
$user->username = 'admin';
$user->setPassword('securepassword');
$user->generateAuthKey();
$user->save();To verify passwords when logging in:
if ($user->validatePassword($password)) {
// Successful authentication
}We have successfully implemented authentication in Yii2 using identity classes, login forms, session-based authentication, and access control filters. You can now extend this system to include user roles, social logins, and two-factor authentication.
Sign in to join the discussion and post comments.
Sign in