webclz 2015-01-09 16:59:43 54432次浏览 9条评论 14 1 0

在yii2的basic版本中默认是从一个数组验证用户名和密码,如何改为从数据表中查询验证呢?
首先新建立一个user表并插入实验数据,如下

CREATE TABLE `user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL,
  `password` varchar(32) NOT NULL,
  `authKey` varchar(100) NOT NULL DEFAULT '',
  `accessToken` varchar(100) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of myuser
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'admin', '123', '1234', '1234');
INSERT INTO `user` VALUES ('2', 'demo', '234', '123', '123');   

模型User.php如下,替换掉原来的User.php就可以实现数据表验证登陆了

namespace app\models;

class User extends /*\yii\base\Object*/ \yii\db\ActiveRecord implements \yii\web\IdentityInterface
{
    /*public $id;
    public $username;
    public $password;
    public $authKey;
    public $accessToken;

    private static $users = [
        '100' => [
            'id' => '100',
            'username' => 'admin',
            'password' => 'admin',
            'authKey' => 'test100key',
            'accessToken' => '100-token',
        ],
        '101' => [
            'id' => '101',
            'username' => 'demo',
            'password' => 'demo',
            'authKey' => 'test101key',
            'accessToken' => '101-token',
        ],
    ];
    */

    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'user';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['username', 'password'], 'required'],
            [['username'], 'string', 'max' => 50],
            [['password'], 'string', 'max' => 32],
            [['authKey'], 'string', 'max' => 100],
            [['accessToken'], 'string', 'max' => 100],
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'username' => 'Username',
            'password' => 'Password',
            'authKey' => 'AuthKey',
            'accessToken' => 'AccessToken',
        ];
    }

    /**
     * @inheritdoc
     */
    public static function findIdentity($id)
    {
        return static::findOne($id);
        //return isset(self::$users[$id]) ? new static(self::$users[$id]) : null;
    }

    /**
     * @inheritdoc
     */
    public static function findIdentityByAccessToken($token, $type = null)
    {
        return static::findOne(['access_token' => $token]);
        /*foreach (self::$users as $user) {
            if ($user['accessToken'] === $token) {
                return new static($user);
            }
        }

        return null;*/
    }

    /**
     * Finds user by username
     *
     * @param  string      $username
     * @return static|null
     */
    public static function findByUsername($username)
    {
          $user = User::find()
            ->where(['username' => $username])
            ->asArray()
            ->one();

            if($user){
            return new static($user);
        }

        return null;
        /*foreach (self::$users as $user) {
            if (strcasecmp($user['username'], $username) === 0) {
                return new static($user);
            }
        }

        return null;*/
    }

    /**
     * @inheritdoc
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @inheritdoc
     */
    public function getAuthKey()
    {
        return $this->authKey;
    }

    /**
     * @inheritdoc
     */
    public function validateAuthKey($authKey)
    {
        return $this->authKey === $authKey;
    }

    /**
     * Validates password
     *
     * @param  string  $password password to validate
     * @return boolean if password provided is valid for current user
     */
    public function validatePassword($password)
    {
        return $this->password === $password;
    }
}

原来 User.php 是继承了 \yii\base\Object,为什么要继承这个类,是有原因的

\yii\base\Object 中,有构造方法

public function __construct($config = [])
{
    if (!empty($config)) {
        Yii::configure($this, $config);
    }
    $this->init();
}

继续追踪 Yii::configure($this, $config) 代码如下

public static function configure($object, $properties)
{
    foreach ($properties as $name => $value) {
        $object->$name = $value;
    }

    return $object;
}

正是因为有这两个方法,所以在 User.php

public static function findByUsername($username)
{
    foreach (self::$users as $user) {
        if (strcasecmp($user['username'], $username) === 0) {
            return new static($user);
        }
    }

    return null;
}

$user 传递过来,通过 static,返回一个 User 的实例。

当通过数据表查询时候没有必要再继承 \yii\base\Object,因为不必为类似原来类变量赋值了。这个时候需要User.php 继承 \yii\db\ActiveRecord,因为要查询用。

findIdentity 是根据传递的 id 返回对应的用户信息,getId 返回用户id,getAuthKeyvalidateAuthKey是作用于登陆中的--记住我。这个authKey是唯一的,当再次登陆时,从cookie中获取authKey传递给validateAuthKey,验证通过,就登陆成功。

觉得很赞
  • 评论于 2015-01-12 13:09 举报

    现在2.0的模型里面还有命名空间吗?

    2 条回复
    评论于 2015-01-13 12:27 回复

    有的,很多地方都用到了命名空间

    评论于 2015-07-02 17:57 回复

    问问看看了

  • 评论于 2015-01-12 15:50 举报

    感觉这篇文章,是原封不动的从某处搬过来的。

    3 条回复
    评论于 2015-01-13 12:28 回复

    不是原封不动的搬过来的

    评论于 2015-05-27 18:00 回复

    试试啊

    评论于 2015-05-27 18:01 回复

    试试啊啊啊

  • 评论于 2015-03-05 11:20 举报

    太好啦!学习了。亲自试了试,确实可以完美运行。

  • 评论于 2015-03-26 23:10 举报

    为什么我登录成功后,Yii::$app->user->isGuest值还是true?

    1 条回复
    评论于 2015-11-09 09:58 回复

    这个问题你弄出来?

  • 评论于 2015-07-29 17:35 举报

    advanced版本好像是有个status字段的?

  • 评论于 2015-08-11 11:07 举报

    我试了也成功了,但是加密时咋办捏

  • 评论于 2015-11-03 10:14 举报

    我在 https://github.com/bubifengyun/book-yii2-dev-process,准备借助 yiichina 里的教程,编辑成一本书,最后用某高校 LaTeX 论文模板美化一下,每月或者更长时间发布 PDF 教程总结,求支持。

    我想把你的教程录入到这本书里,并记录您的名字及原网址,可否?谢谢啦。

  • 评论于 2016-09-22 16:20 举报

    提示这个,Call to undefined method app\models\User::findByUsername()。不知道该咋办?

  • 评论于 2016-11-01 00:09 举报

    如果有ip,time,role等字段呢?yii提供的登陆一样吗?

您需要登录后才可以评论。登录 | 立即注册