T-DOC
  • Laravel-11
  • Laravel-10
  • Laravel-6X
  • Laravel-5.5
Dcat-Admin
  • Yii2
  • 重构2
  • Laravel-11
  • Laravel-10
  • Laravel-6X
  • Laravel-5.5
Dcat-Admin
  • Yii2
  • 重构2
  • 前言

    • 关于 Yii
    • 从 Yii 1.1 升级
    • Yii 2.0 升级说明
    • 贡献者指引
    • 捐献和赞助
  • 版本管理

    • 发行说明
    • 版本说明
    • 更新记录
  • 快速入门

    • 安装 Yii
    • 目录结构
    • 部署
    • Hello world
    • 使用表单
    • 使用数据库
    • 使用 Gii 生成代码
    • 编辑器与 IDE
  • 核心架构

    • 请求生命周期
    • 单一入口
    • 应用主体
    • 组件
    • 属性
    • 事件
    • 行为
    • 配置
    • 别名
    • 类自动加载
    • 服务定位器
    • 依赖注入容器
  • 高级应用模板

    • 安装
    • 框架结构
    • 运行测试
    • 环境与配置
    • 自定义应用模板
  • 基础功能

    • 路由
    • 控制器
    • 过滤器
    • 请求
    • 响应
    • 模型
    • 视图
    • 模块
    • 小部件
    • 前端资源
    • 扩展
    • Sessions 和 Cookies
    • 错误处理
    • 日志
  • 数据库

    • 数据库访问对象(DAO)
    • 查询构造器
    • 活动记录
    • 数据库迁移
    • Redis
    • Sphinx
    • Elasticsearch
    • MongoDB
  • 安全

    • 认证
    • 授权
    • 加密
    • Email 认证
    • 验证码
    • 社会化登录
    • 密码
  • 进阶功能

    • 缓存
    • 发送邮件
    • HTTP 客户端
    • 国际化
    • 队列
    • 控制台应用
    • 助手类
    • 验证器
  • RESTful Web 服务

    • 快速入门
    • 资源
    • 控制器
    • 路由
    • 格式化响应
    • 认证
    • 速率限制(限流)
    • 版本化
    • 错误处理
  • 开发工具

    • 调试工具栏和调试器
    • 使用 Gii 生成代码

认证

认证是鉴定用户身份的过程。它通常使用一个标识符,例如用户名、手机号或电子邮件地址等,再加上一个加密令牌,比如密码、短信验证码或存取令牌(access token)等,然后用它们来认证用户的身份。认证是登录功能的基础。

Yii提供了一个认证框架,它连接了不同的组件以支持登录。欲使用这个框架,你主要需要做以下工作:

  • 设置用户组件 yii\web\User;
  • 创建一个类实现 yii\web\IdentityInterface 接口。

配置用户组件

用户组件 yii\web\User 用来管理用户的认证状态。这需要你指定一个含有实际认证逻辑的认证类 yii\web\User::identityClass。在以下web应用的配置项中,将用户用户组件 yii\web\User 的认证类 yii\web\User::identityClass 配置成模型类,例如:app\models\User,它的实现将在下一节中讲述。

return [
    'components' => [
        'user' => [
            'identityClass' => 'app\models\User',
        ],
    ],
];

认证接口的实现

认证类 yii\web\User::identityClass 必须实现包含以下方法的 认证接口 yii\web\IdentityInterface:

  • yii\web\IdentityInterface::findIdentity():根据指定的用户ID查找认证模型类的实例,当你需要使用 session 来维持登录状态的时候会用到这个方法。
  • yii\web\IdentityInterface::findIdentityByAccessToken():根据指定的存取令牌查找认证模型类的实例,该方法用于通过单个加密令牌认证用户的时候(比如无状态的 RESTful 应用)。
  • yii\web\IdentityInterface::getId():获取该认证实例表示的用户的 ID。
  • yii\web\IdentityInterface::getAuthKey():获取基于 cookie 自动登录时使用的认证密钥。认证密钥储存在 cookie 里并且将来会与服务端的版本进行比较以确保 cookie 的有效性。
  • yii\web\IdentityInterface::validateAuthKey():是基于 cookie 登录密钥的验证的逻辑的实现。

用不到的方法可以空着,例如,你的项目只是一个无状态的 RESTful 应用,只需实现 yii\web\IdentityInterface::findIdentityByAccessToken() 和 yii\web\IdentityInterface::getId(),其他的方法的函数体留空即可。

我们可以通过一个结合了 user 数据表的 AR 模型 Active Record 实现的一个认证类 yii\web\User::identityClass,代码如下:

<?php

use yii\db\ActiveRecord;
use yii\web\IdentityInterface;

class User extends ActiveRecord implements IdentityInterface
{
    public static function tableName()
    {
        return 'user';
    }

    /**
     * 根据给到的ID查询身份。
     *
     * @param string|integer $id 被查询的ID
     * @return IdentityInterface|null 通过ID匹配到的身份对象
     */
    public static function findIdentity($id)
    {
        return static::findOne($id);
    }

    /**
     * 根据 token 查询身份。
     *
     * @param string $token 被查询的 token
     * @return IdentityInterface|null 通过 token 得到的身份对象
     */
    public static function findIdentityByAccessToken($token, $type = null)
    {
        return static::findOne(['access_token' => $token]);
    }

    /**
     * @return int|string 当前用户ID
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @return string 当前用户的(cookie)认证密钥
     */
    public function getAuthKey()
    {
        return $this->auth_key;
    }

    /**
     * @param string $authKey
     * @return boolean if auth key is valid for current user
     */
    public function validateAuthKey($authKey)
    {
        return $this->getAuthKey() === $authKey;
    }
}

如上所述,如果你的应用利用 cookie 登录,你只需要实现 getAuthKey() 和 validateAuthKey() 方法。这样的话,你可以使用下面的代码在 user 表中生成和存储每个用户的认证密钥。

class User extends ActiveRecord implements IdentityInterface
{
    ......

    public function beforeSave($insert)
    {
        if (parent::beforeSave($insert)) {
            if ($this->isNewRecord) {
                $this->auth_key = \Yii::$app->security->generateRandomString();
            }
            return true;
        }
        return false;
    }
}

Note: 不要混淆 user 认证类和用户组件 yii\web\User。前者是实现认证逻辑的类,通常用关联了持久性存储的用户信息的 AR 模型 Active Record 实现。后者是负责管理用户认证状态的应用组件。

使用用户组件

在 user 应用组件方面,你主要用到 yii\web\User 。

你可以使用表达式 Yii::$app->user->identity 检测当前用户身份。它返回一个表示当前登录用户的认证类 yii\web\User::identityClass 的实例,未认证用户(即游客)则返回 null。下面的代码展示了如何从 yii\web\User 获取其他认证相关信息:

// 当前用户的身份实例。未认证用户则为 Null 。
$identity = Yii::$app->user->identity;

// 当前用户的ID。 未认证用户则为 Null 。
$id = Yii::$app->user->id;

// 判断当前用户是否是游客(未认证的)
$isGuest = Yii::$app->user->isGuest;

你可以使用下面的代码登录用户:

// 使用指定用户名获取用户身份实例。
// 请注意,如果需要的话您可能要检验密码
$identity = User::findOne(['username' => $username]);

// 登录用户
Yii::$app->user->login($identity);

yii\web\User::login() 方法将当前用户的身份登记到 yii\web\User。如果 session 设置 yii\web\User::enableSession 属性值为 true,则使用 session 记录用户身份,用户的认证状态将在整个会话中得以维持。如果开启自动登录 yii\web\User::enableAutoLogin 属性为 true,则基于 cookie 自动登录(如:记住登录状态),它将使用 cookie 保存用户身份,这样只要 cookie 有效就可以恢复登录状态。

为了使用 cookie 自动登录,你需要在应用配置文件中将 yii\web\User::enableAutoLogin 属性值设为 true。你还需要在 yii\web\User::login() 方法中传递有效期(记住登录状态的时长)参数。

注销用户:

Yii::$app->user->logout();

请注意,启用 session 时注销用户才有意义。该方法将从内存和 session 中同时清理用户认证状态。默认情况下,它还会注销所有的用户会话数据。如果你希望保留这些会话数据,可以换成 Yii::$app->user->logout(false)。

认证事件

yii\web\User 类在登录和注销流程引发一些事件。

  • yii\web\User::EVENT_BEFORE_LOGIN:在登录 yii\web\User::login() 时引发。如果事件句柄将事件对象的 yii\web\UserEvent::isValid 属性设为 false,登录流程将会被取消。
  • yii\web\User::EVENT_AFTER_LOGIN:登录成功后引发。
  • yii\web\User::EVENT_BEFORE_LOGOUT:注销 yii\web\User::logout() 前引发。如果事件句柄将事件对象的 yii\web\UserEvent::isValid 属性设为 false,注销流程将会被取消。
  • yii\web\User::EVENT_AFTER_LOGOUT:成功注销后引发。

你可以通过响应这些事件来实现一些类似登录统计、在线人数统计的功能。例如, 在登录后 yii\web\User::EVENT_AFTER_LOGIN 的处理程序,你可以将用户的登录时间和IP记录到 user 表中。

💖喜欢本文档的,欢迎点赞、收藏、留言或转发,谢谢支持!
作者邮箱:zhuzixian520@126.com,github地址:github.com/zhuzixian520

Last Updated:
Contributors: Hans
Next
授权