Authorization - uniqcle/Yii2 GitHub Wiki
3 процедуры взаимосвязаны:
- Сначала определяют имя (логин или номер) – идентификация
- Затем проверяют пароль (ключ или отпечаток пальца) – аутентификация
- И в конце предоставляют доступ – авторизация
Подробно: Идентификация, аутентификация, авторизация
Вход на сайт
- username // Идентификация
- password // Аутентификация
Логин:
1) Ввод данных в форму, отправить
2) Загрузка данных в модель
3) Валидиация
3.1 Используя username, найти запись в БД
3.2 Сверить пароль в записи БД и пароль из формы
4) Запомнить пользователя
Контроллер frontend\controllers\UserController.php
namespace frontend\controllers;
use Yii;
use frontend\models\forms\SignupForm;
use frontend\models\forms\LoginForm;
class UserController extends \yii\web\Controller
{
//Register
public function actionSignup()
{
$model = new SignupForm();
if($model->load( Yii::$app->request->post() ) && $model->save() ){
Yii::$app->session->setFlash('success', 'New user added!');
return $this->redirect(['site/index']);
}
return $this->render('signup', [
'model' => $model
]);
}
//LogIn
public function actionLogin()
{
$model = new LoginForm();
if( $model->load( Yii::$app->request->post() ) && $model->login() ){
return $this->redirect(['site/index']);
}
return $this->render('login', [
'model' => $model
]);
}
//LogOut
public function actionLogout(){
Yii::$app->user->logout();
return $this->redirect(['site/index']);
}
}
Модель frontend\models\forms\LoginForm.php
namespace frontend\models\forms;
use Yii;
use yii\base\Model;
use frontend\models\User;
class LoginForm extends Model
{
public $username;
public $password;
public function rules(){
return [
['username', 'trim'],
['username', 'required'],
['password', 'required'],
['password', 'validatePassword']
];
}
public function login(){
if( $this->validate() ){
//Находим пользователя по его username
$user = User::findUserByName($this->username);
//Скармливаем пользователя компоненту user
return Yii::$app->user->login($user);
}
return false;
}
//Собственные валидаторы ничего не должны возвращать. Единственное в случае ошибки - вызывать метод addError() в случае ошибки.
public function validatePassword($attribute, $params){
//Находим пользователя по username
$user = User::findUserByName($this->username);
//Если полльзователь есть
if( $user ){
//Сверяем пароли в модели user.
if( !$user->validatePassword($this->password) ){
$this->addError($attribute, 'Неверный пароль');
}
}
}
}
Модель frontend\models\User.php
namespace frontend\models;
use Yii;
use yii\web\IdentityInterface;
/**
* This is the model class for table "user".
*
* @property int $id
* @property string $username
* @property string $auth_key
* @property string $password_hash
* @property string $password_reset_token
* @property string $email
* @property int $status
* @property int $created_at
* @property int $updated_at
*/
class User extends \yii\db\ActiveRecord implements IdentityInterface
{
public static function tableName()
{
return 'user';
}
public function rules()
{
return [
[['username', 'auth_key', 'password_hash', 'email', 'created_at', 'updated_at'], 'required'],
[['status', 'created_at', 'updated_at'], 'integer'],
[['username', 'password_hash', 'password_reset_token', 'email'], 'string', 'max' => 255],
[['auth_key'], 'string', 'max' => 32],
[['username'], 'unique'],
[['email'], 'unique'],
[['password_reset_token'], 'unique'],
];
}
public function attributeLabels()
{
return [
'id' => 'ID',
'username' => 'Username',
'auth_key' => 'Auth Key',
'password_hash' => 'Password Hash',
'password_reset_token' => 'Password Reset Token',
'email' => 'Email',
'status' => 'Status',
'created_at' => 'Created At',
'updated_at' => 'Updated At',
];
}
public static function findUserByName($username){
return self::find()->where(['username' => $username])->one();
}
//Валидация пароля пользователя
public function validatePassword( $password ){
// if( Yii::$app->security->validatePassword( $password, $this->password_hash ) === false )
// или так
return Yii::$app->security->validatePassword( $password, $this->password_hash );
}
//IDENTITY INTERFACE
public static function findIdentity($id)
{
return static::findOne($id);
}
/**
* Finds an identity by the given token.
*
* @param string $token the token to be looked for
* @return IdentityInterface|null the identity object that matches the given token.
*/
public static function findIdentityByAccessToken($token, $type = null)
{
return static::findOne(['access_token' => $token]);
}
/**
* @return int|string current user ID
*/
public function getId()
{
return $this->id;
}
/**
* @return string current user auth key
*/
public function getAuthKey()
{
return $this->auth_key;
}
/**
* @param string $authKey
* @return bool if auth key is valid for current user
*/
public function validateAuthKey($authKey)
{
return $this->getAuthKey() === $authKey;
}
}
Вью frontend\views\user\login.php
/* @var $this yii\web\View */
/* @var $form yii\bootstrap\ActiveForm */
/* @var $model \frontend\models\LoginForm */
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
$this->title = 'Login User';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-signup">
<h1><?= Html::encode($this->title) ?></h1>
<p>Please fill out the following fields to login:</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'form-signup']); ?>
<?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<div class="form-group">
<?= Html::submitButton('Signup', ['class' => 'btn btn-primary', 'name' => 'signup-button']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>
Настройки frontend\config\main.php
...
'user' => [
//Указываем класс в качестве Identity
'identityClass' => 'frontend\models\User',
'enableAutoLogin' => true,
'identityCookie' => ['name' => '_identity-frontend', 'httpOnly' => true],
],
...
Настройки меню frontend\views\layouts\main.php
...
<?php
NavBar::begin([
'brandLabel' => Yii::$app->name,
'brandUrl' => Yii::$app->homeUrl,
'options' => [
'class' => 'navbar-inverse navbar-fixed-top',
],
]);
$menuItems = [
['label' => 'Home', 'url' => ['/site/index']],
['label' => 'Authors', 'url' => ['/lib/author/index']],
['label' => 'Publisher', 'url' => ['/lib/publisher/index']],
['label' => 'About', 'url' => ['/site/about']],
['label' => 'Contact', 'url' => ['/site/contact']],
];
if (Yii::$app->user->isGuest) {
$menuItems[] = ['label' => 'Signup', 'url' => ['/user/signup']];
$menuItems[] = ['label' => 'Login', 'url' => ['/user/login']];
} else {
$menuItems[] = '<li>'
. Html::beginForm(['/user/logout'], 'post')
. Html::submitButton(
'Logout (' . Yii::$app->user->identity->username . ')',
['class' => 'btn btn-link logout']
)
. Html::endForm()
. '</li>';
}
echo Nav::widget([
'options' => ['class' => 'navbar-nav navbar-right'],
'items' => $menuItems,
]);
NavBar::end();
?>
...
Вывод в любом View
...
//var_dump( Yii::$app->user->identity );
if( Yii::$app->user->isGuest ){
echo '<h3> Добро пожаловать, гость! </h3>';
} else {
echo '<h3> Добро пожаловать, '. Yii::$app->user->identity->username.' ! </h3>';
}
...