Yii2 Login机制详解

1、背景

Yii2提供了默认的登录机制,今天我们来详细解读一下源码,看一下它是怎么工作的。

2、登录路由

2.1 登录页面

我们通过url可以找到登录的控制器入口,url如下:

http://172.22.0.3/index.php?r=site%2Flogin

因此入口应该是backend/controllers/SiteController.phpactionLogin()方法:

    public function actionLogin()
    {
        if (!Yii::$app->user->isGuest) {
            return $this->goHome();
        }

        $this->layout = 'blank';

        $model = new LoginForm();
        if ($model->load(Yii::$app->request->post()) && $model->login()) {
            return $this->goBack();
        } else {
            $model->password = '';

            return $this->render('login', [
                'model' => $model,
            ]);
        }
    }

通过访问这个方法,用$this->render实现MVC模式,渲染页面,从而浏览器展示登录页面,从代码中可以看到,view页面所在位置是:backend/views/site/login.php

2.2 登录请求

在登录页面填好账号密码后,点击登录按钮,请求到哪里去呢?从页面的元素中我们可以看到,其实就是把请求投递到当前页面所在的控制器,因为action的值和当前页面的url是一致的:

<form id="login-form" action="/index.php?r=site%2Flogin" method="post">

3、LoginForm

common/models/LoginForm.php是对登录验证的主要模型,这个模型继承于yii\base\Model,因此可以使用Yii提供的数据验证机制来实现数据有效性验证。

3.1 load()

$model->load(Yii::$app->request->post())这个方法会把请求过来的数据填充到LoginForm->attributes中,也就是对类属性赋值,其实load($data, $formName = null)还有第二个参数,用于指定$formName,为啥要这个属性呢?因为post过来的数据有多个层次,如下:

array(3) {
  ["_csrf-backend"]=>
  string(88) "BGsAOWgj1SMXlli3QpPFaZClyaac9_9gErgS9Bk_Vw88DWtsOGyWG3LkHM0l9qscvcT45d6dpRVFiV2SWn0iSg=="
  ["LoginForm"]=>
  array(3) {
    ["username"]=>
    string(2) "ad"
    ["password"]=>
    string(6) "123456"
    ["rememberMe"]=>
    string(1) "0"
  }
  ["login-button"]=>
  string(0) ""
}

yii需要知道$formName = "LoginForm"才能从post中的数据获取属性值。但是上述代码中并没有指定$formName,从源代码可知,如果$formName不设置,会取当前类名称作为它的值。

3.2 login()
<?php
namespace common\models;
... ... 
class LoginForm extends Model
{
	public function login()
    {
        if ($this->validate()) {
            return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);
        }

        return false;
    }
	... ... 
}

此处正是验证用户名和密码的核心代码,由于LoginForm()继承于yii\base\Model,因此可以使用验证器,代码通过$this->validate()进行验证数据有效性,验证规则如下:

<?php
namespace common\models;
... ... 
class LoginForm extends Model
{
	public function rules()
    {
        return [
            // username and password are both required
            [['username', 'password'], 'required'],
            // rememberMe must be a boolean value
            ['rememberMe', 'boolean'],
            // password is validated by validatePassword()
            ['password', 'validatePassword'],
        ];
    }
    ... ... 
}

通过上述规则可以实现如下功能:

usernamepassword是必须要有的属性,就是说点击登录按钮后必须要传进来的参数,否则的话会报如下错误:
在这里插入图片描述

password还有一条验证规则,就是通过validatePassword方法进行验证:

<?php
namespace common\models;
... ... 
class LoginForm extends Model
{
 	public function validatePassword($attribute, $params)
    {
        if (!$this->hasErrors()) {
            $user = $this->getUser();
            if (!$user || !$user->validatePassword($this->password)) {
                $this->addError($attribute, 'Incorrect username or password.');
            }
        }
    }
	... ... 
}

从代码可知,如果前面的验证规则都通过了才会进入密码正确性验证,系统会通过$this->getUser()这个方法以username为条件搜索用户表,并返回User模型实例:

<?php
namespace common\models;
... ... 
class LoginForm extends Model
{
	protected function getUser()
    {
        if ($this->_user === null) {
            $this->_user = User::findByUsername($this->username);
        }

        return $this->_user;
    }
    ... ...
}

有了User模型实例,就可以通过$user->validatePassword($this->password)来对密码进行验证,验证通过后,会进入Yii::$app->user->login(),将当前的认证信息切换到当前的用户,注意:

Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);

此处$this->rememberMe的作用就是维持用户的登录态:

  • 0:浏览器关闭后或者手动清除session后,登录态失效;
  • 1:登录态会保持到3600 * 24 * 30,即:30天后失效。

以后我们会有专门的章节对登录态的机制进行详细的讲解。

3.3 goBack()

登录成功后,会回到请求发起的页面重新请求一次,由于此时已经保存了用户认证信息,Yii::$app->user->isGuest已经为非,因此会跳转到$this->goHome(),进入系统Home目录;

3.4 登录失败

如果登录失败,则会$model->password = '';清除密码,返回到系统登录页面,提示如下信息,要求重新输入密码:
在这里插入图片描述

4 未完待续

关于系统是如何渲染出html元素,如何对用户输入的数据进行反应,报错信息如何动态展示,这些是都是小部件ActiveForm的封装,它的行为取决于我们在Model类中对属性的约束,由于ActiveForm比较复杂,我们会在小部件篇专门介绍,本文主要讲解登录机制,因此不作深入探索。

关注我的微信公众号,更多推送不遗漏!
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值