回顾yii2用户注册与登录

前言:

很久没用yii2写登录了。有些细节都有些忘了,写一篇加深下印象,本次做的用户登录,使用的是yii2 user组件中的login方法来保存用户登录状态,这也是yii2比较优秀的地方,很多地方不用我们操心

目录:

  1. 使用数据迁移,完成建表
  2. 完成注册
  3. 完成登录

  1. 使用数据迁移,完成建表
    yii2中自带了一个user表的数据迁移
数据迁移

我们在控制台目录下找到它的位置
然后用命令行来执行数据迁移

image.png

当数据表建好了之后,我们需要在表中添加一个字段

数据表

就是最后的salt(盐值),字符形 32位,这个主要是用于密码加密,是目前比较流行的也是安全性比较高的加密方式


  1. 完成注册

注册页面我选择使用ActiveForm来做一个表单,需要使用ActiveForm就必须在渲染视图方法中给页面传递一个模型对象来配合使用

    /**
     * 渲染注册页面
     */
    public function actionRegist()
    {
        $userModle = new User();
        return $this->render('regist', ['usermodel' => $userModle]);
    }

由于只是测试使用,并不是实际工作开发,这里注册就只做了账号密码和邮箱,并且没有涉及发邮件技术,如果对发邮件感兴趣的朋友可以点击看我另一篇博客yii2发邮件。这里就不多介绍了

页面我选用了bootstrap框架来做一个简单的表单

image.png

下面来看控制器部分

  /**
     * 完成注册
     */
    public function actionRegistTodo()
    {
        //通过自己封装的私有方法来接收前台提交的表单数据
        $formData = $this->_getRequest();
        //创建模型对象
        $userModel = new User();
        //将数据绑定到模型对象中
        if (!$userModel->load($formData)) {
            exit('绑定数据错误');
        }
        try {
            //调用模型中的创建用户的方法
            if ($userModel->createUser()) {
                echo '注册成功';
            }
            //捕获创建新用户方法中抛出的异常
        } catch (Exception $exception) {
            //打印异常的信息
            var_dump($exception->getMessage());
        }
    }

控制器部分方法比较简洁,重点是控制器中调用的模型层的createUser方法

在创建用户之前,我们需要对前台传递过来的数据进行验证,我们知道程序员永远不能相信用户提交的数据,对于用户的提交,验证是必须的

由于我们的模型类继承了ActiveRecord

class User extends \yii\db\ActiveRecord

所以我们可以使用父类中的validate方法来验证表单数据

     if (!$this->validate()) {
            throw new Exception($this->getErrors());
     }

当调用validate方法后,它会获取到们之前写好的rules方法里面的验证规则,如果数据符合验证规则,返回true,不符合返回false,并且会将不匹配的提示信息绑定到模型对象上,我们可以通过getErrors方法来获取

验证方法

当验证通过后,我们就可以对密码进行加密了,我们使用加盐加密。

  1. 首先我们需要生成随机的盐值
$salt=Yii::$app->security->generateRandomString();

我们调用secrurity组件上的generateRandomString方法来生成一个32位的随机数

  1. 将用户输入的密码和盐值拼接,随后用security组件中的哈希方法进行加密
 $this->password_hash=Yii::$app->security->generatePasswordHash($this->password_hash.$salt);

加密方式按个人喜好,也可使用md5加密

  1. 将生成的盐值绑定到模型对象上
$this->salt=$salt;

盐值需要保存到数据库中,用于用户登录时进行加密对比

  1. 保存到数据库中
    if (!$this->save(false)) {
            throw new Exception($this->getErrors());
    }

由于其他数据在通过load方法绑定到模型上,我们将加密后的密码和盐值绑定上后,就可以保存到数据库中了

这里有个小细节,当我们调用模型中的save方法保存数据的时候,save方法还会调用validate来验证数据,由于我的验证规则中有验证两次输入密码必须一致,当我们的密码加密后,就和之前的重复密码不一致了,这样就会导致报错。解决方法就是在save方法中传入一个false,这样就不会在save的同时进行验证了


  1. 完成登录

同样的,登录我们也是使用的ActiveForm和Bootstrap框架来写表单,不同的是,我们登录还加入了验证码 (验证码这次就不细谈了)

  1. 前端页面部分
<?php $form = \yii\bootstrap\ActiveForm::begin(['action' => \yii\helpers\Url::to(['login/login-check'])]) ?>
<table>
    <tr>
<!--        用户名-->
        <?= $form->field($model, 'username') ?>
    </tr>
    <tr>
<!--        密码-->
        <?= $form->field($model, 'password_hash') ?>
    </tr>
    <tr>
<!--        重复密码-->
        <?= $form->field($model, 'repassword') ?>
    </tr>
    <tr>
<!--        验证码图片-->
        <td><img style="cursor:pointer;" id="captchaImg" src="<?= \yii\helpers\Url::to(['login/captcha']) ?>" alt=""></td>
    </tr>
    <tr>
        <td>
            <label for="captcha">验证码</label>
<!--            验证码输入框-->
            <input type="text" name="captcha" class="input-xxlarge">
        </td>
    </tr>
    <tr>
        <td><input type="submit" value="提交" class="btn btn-success"></td>
        <td><a class="btn btn-warning" href="<?=\yii\helpers\Url::to(['login/regist'])?>">注册</a></td>
    </tr>
</table>
<?php $form::end(); ?>

前面已经介绍过页面,登录页面和注册页面类似。

  1. 控制器部分

首先是判断验证码是否正确

验证码

绑定数据,验证数据

验证数据

调用模型方法,查找用户,如果账号密码匹配,调用user组件中的login方法完成登录

完成登录

在绑定数据验证数据的时候,有个小细节,这时我们的业务只需要验证用户名和密码,并不需要验证邮箱,可我们的验证规则中写了邮箱。或则在以后我们验证规则中别的什么字段的时候,我们可以采取部分验证

        //验证部分数据(只验证用户名,密码,重复密码)
        if (!$userModel->validate(['username','password_hash','repassword'])) {
            die('数据非法');
        }

将要验证的字段以数组形式传入validate就可以了,这样就只会验证你传入的字段的验证规则.我称之为部分验证

  1. 模型部分

首先我们要使用yii2自带的login方法来保存登录状态,我们需要我们的user模型继承IdentityInterface身份验证接口,并且实现它里面的抽象方法

继承接口

下面是实现接口的代码

/**
     * 通过传递的id,返回查到的数据模型对象的静态方法
     * @param int|string $id
     * @return static
     */
    public static function findIdentity($id)
    {
        return User::findOne($id);
    }

    /**
     * 通过传递token,返回查到的数据模型对象的静态方法
     * @param mixed $token
     * @param null $type
     * @return static
     */
    public static function findIdentityByAccessToken($token, $type = null)
    {
        return User::findOne(['password_reset_token'=>$token]);
    }

    /**
     * 返回当前对象的id
     * @return string
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * 获取当前对象的auth_key
     * @return mixed
     */
    public function getAuthKey()
    {
        return $this->auth_key;

    }

    /**
     *对比传递过来的authkey于当前对象的auth_key
     * @param string $authKey
     * @return bool
     * 返回对比结果
     */
    public function validateAuthKey($authKey)
    {
        return $authKey===$this->getAuthKey();
    }

前面的准备工作,搞定过后,我们就可以来完成登录验证
我们登录分三部

  1. 获取用户输入的用户名,判断是否有这个用户
  2. 将盐值从数据库中取出,并于用户输入的密码拼接
  3. 将加密后的用户输入的密码,和数据库中存储的密码进行比对

任意一步失败,则抛出异常

第一部

        $username=$this->username;
        $password_hash=$this->password_hash;
        //查询数据表中用户名
        $userModel=User::findOne(['username'=>$username]);
        if (empty($userModel)) {
            throw new Exception('用户或密码错误');
        }

第二部

        //账号存在,对比密码
        $salt=$userModel->salt;
        //用户表单提交的密码加密
        $securityPassword=$password_hash.$salt;

拼接后的密码不需要进行hash加密,我们使用yii2 security组件中的validatePassword的方法来比对

第三部

      if (!Yii::$app->security->validatePassword($securityPassword,$userModel->password_hash)) {
            throw new Exception('用户或密码错误');
      }
        return $userModel;

密码验证通过后,则返回查找到的数据模型对象
控制器获取到了数据模型对象后就可以调用user组件中的login方法,进行保存用户登录的状态了

好了,本次回顾yii2登录注册的介绍了就写到这里了,如果有什么地方不对,希望大神指正.谢谢

以上

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容