# 认证
认证是鉴定用户身份的过程。它通常使用一个标识符 (如用户名或电子邮件地址)和一个加密令牌(比如密码或者存取令牌)来 鉴别用户身份。认证是登录功能的基础。
Yii提供了一个认证框架,它连接了不同的组件以支持登录。欲使用这个框架, 你主要需要做以下工作:
* 设置用户组件 yii\web\User ;
* 创建一个类实现 yii\web\IdentityInterface 接口。
## 配置 yii\web\User
用户组件 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\IdentityInterface 的实现
认证类 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](http://www.yiichina.com/doc/guide/2.0/db-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;
}
}
~~~
> 注意:不要混淆 `user` 认证类和用户组件 yii\web\User。前者是实现 认证逻辑的类,通常用关联了 持久性存储的用户信息的AR模型 [Active Record](http://www.yiichina.com/doc/guide/2.0/db-active-record) 实现。后者是负责管理用户认证状态的 应用组件。
## 使用用户组件 yii\web\User
在 `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,则使用 session 记录用户身份,用户的 认证状态将在整个会话中得以维持。如果开启自动登录 yii\web\User::enableAutoLogin 则基于 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` 表中。
- 介绍(Introduction)
- 关于 Yii(About Yii)
- 从 Yii 1.1 升级(Upgrading from Version 1.1)
- 入门(Getting Started)
- 安装 Yii(Installing Yii)
- 运行应用(Running Applications)
- 第一次问候(Saying Hello)
- 使用 Forms(Working with Forms)
- 玩转 Databases(Working with Databases)
- 用 Gii 生成代码(Generating Code with Gii)
- 更上一层楼(Looking Ahead)
- 应用结构(Application Structure)
- 结构概述(Overview)
- 入口脚本(Entry Scripts)
- 应用(Applications)
- 应用组件(Application Components)
- 控制器(Controllers)
- 模型(Models)
- 视图(Views)
- 模块(Modules)
- 过滤器(Filters)
- 小部件(Widgets)
- 前端资源(Assets)
- 扩展(Extensions)
- 请求处理(Handling Requests)
- 运行概述(Overview)
- 引导(Bootstrapping)
- 路由引导与创建 URL(Routing and URL Creation)
- 请求(Requests)
- 响应(Responses)
- Sessions and Cookies
- 错误处理(Handling Errors)
- 日志(Logging)
- 关键概念(Key Concepts)
- 组件(Components)
- 属性(Properties)
- 事件(Events)
- 行为(Behaviors)
- 配置(Configurations)
- 别名(Aliases)
- 类自动加载(Class Autoloading)
- 服务定位器(Service Locator)
- 依赖注入容器(Dependency Injection Container)
- 配合数据库工作(Working with Databases)
- 数据库访问(Data Access Objects): 数据库连接、基本查询、事务和模式操作
- 查询生成器(Query Builder): 使用简单抽象层查询数据库
- 活动记录(Active Record): 活动记录对象关系映射(ORM),检索和操作记录、定义关联关系
- 数据库迁移(Migrations): 在团体开发中对你的数据库使用版本控制
- Sphinx
- Redis
- MongoDB
- ElasticSearch
- 接收用户数据(Getting Data from Users)
- 创建表单(Creating Forms)
- 输入验证(Validating Input)
- 文件上传(Uploading Files)
- 收集列表输入(Collecting Tabular Input)
- 多模型同时输入(Getting Data for Multiple Models)
- 显示数据(Displaying Data)
- 格式化输出数据(Data Formatting)
- 分页(Pagination)
- 排序(Sorting)
- 数据提供器(Data Providers)
- 数据小部件(Data Widgets)
- 操作客户端脚本(Working with Client Scripts)
- 主题(Theming)
- 安全(Security)
- 认证(Authentication)
- 授权(Authorization)
- 处理密码(Working with Passwords)
- 客户端认证(Auth Clients)
- 安全领域的最佳实践(Best Practices)
- 缓存(Caching)
- 概述(Overview)
- 数据缓存(Data Caching)
- 片段缓存(Fragment Caching)
- 分页缓存(Page Caching)
- HTTP 缓存(HTTP Caching)
- RESTful Web 服务
- 快速入门(Quick Start)
- 资源(Resources)
- 控制器(Controllers)
- 路由(Routing)
- 格式化响应(Response Formatting)
- 授权验证(Authentication)
- 速率限制(Rate Limiting)
- 版本化(Versioning)
- 错误处理(Error Handling)
- 开发工具(Development Tools)
- 调试工具栏和调试器(Debug Toolbar and Debugger)
- 使用 Gii 生成代码(Generating Code using Gii)
- TBD 生成 API 文档(Generating API Documentation)
- 测试(Testing)
- 概述(Overview)
- 搭建测试环境(Testing environment setup)
- 单元测试(Unit Tests)
- 功能测试(Functional Tests)
- 验收测试(Acceptance Tests)
- 测试夹具(Fixtures)
- 高级专题(Special Topics)
- 高级应用模版(Advanced Project Template)
- 从头构建自定义模版(Building Application from Scratch)
- 控制台命令(Console Commands)
- 核心验证器(Core Validators)
- 国际化(Internationalization)
- 收发邮件(Mailing)
- 性能优化(Performance Tuning)
- 共享主机环境(Shared Hosting Environment)
- 模板引擎(Template Engines)
- 集成第三方代码(Working with Third-Party Code)
- 小部件(Widgets)
- Bootstrap 小部件(Bootstrap Widgets)
- jQuery UI 小部件(jQuery UI Widgets)
- 助手类(Helpers)
- 助手一览(Overview)
- Array 助手(ArrayHelper)
- Html 助手(Html)
- Url 助手(Url)