新建api\models\LoginForm.PHP
<?php
namespace api\models;
use Yii;
use yii\base\Model;
use common\models\User;
/**
* Login form
*/
class LoginForm extends Model
{
public $username;
public $password;
private $_user;
const GET_API_TOKEN = 'generate_api_token';
public function init ()
{
parent::init();
$this->on(self::GET_API_TOKEN, [$this, 'onGenerateApiToken']);
}
/**
* @inheritdoc
* 对客户端表单数据进行验证的rule
*/
public function rules()
{
return [
[['username', 'password'], 'required'],
['password', 'validatePassword'],
];
}
/**
* 自定义的密码认证方法
*/
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$this->_user = $this->getUser();
if (!$this->_user || !$this->_user->validatePassword($this->password)) {
$this->addError($attribute, '用户名或密码错误.');
}
}
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'username' => '用户名',
'password' => '密码',
];
}
/**
* Logs in a user using the provided username and password.
*
* @return boolean whether the user is logged in successfully
*/
public function login()
{
if ($this->validate()) {
$this->trigger(self::GET_API_TOKEN);
return $this->_user;
} else {
return null;
}
}
/**
* 根据用户名获取用户的认证信息
*
* @return User|null
*/
protected function getUser()
{
if ($this->_user === null) {
$this->_user = User::findByUsername($this->username);
}
return $this->_user;
}
/**
* 登录校验成功后,为用户生成新的token
* 如果token失效,则重新生成token
*/
public function onGenerateApiToken ()
{
if (!User::apiTokenIsValid($this->_user->api_token)) {
$this->_user->generateApiToken();
$this->_user->save(false);
}
}
}
我们回过头来看一下,当我们在UserController的login操作中调用LoginForm的login操作后都发生了什么
1、调用LoginForm的login方法
2、调用validate方法,随后对rules进行校验
3、rules校验中调用validatePassword方法,对用户名和密码进行校验
4、validatePassword方法校验的过程中调用LoginForm的getUser方法,通过common\models\User类的findByUsername获取用户,找不到或者common\models\User的validatePassword对密码校验失败则返回error
5、触发LoginForm::GENERATE_API_TOKEN事件,调用LoginForm的onGenerateApiToken方法,通过common\models\User的apiTokenIsValid校验token的有效性,如果无效,则调用User的generateApiToken方法重新生成
注意common\models\User类必须是用户的认证类.
下面补充本节增加的common\models\User的相关方法
/**
* 生成 api_token
*/
public function generateApiToken()
{
$this->api_token = Yii::$app->security->generateRandomString() . '_' . time();
}
/**
* 校验api_token是否有效
*/
public static function apiTokenIsValid($token)
{
if (empty($token)) {
return false;
}
$timestamp = (int) substr($token, strrpos($token, '_') + 1);
$expire = Yii::$app->params['user.apiTokenExpire'];
return $timestamp + $expire >= time();
}
继续补充apiTokenIsValid方法中涉及到的token有效期,在api\config\params.php文件内增加即可
<?php return [ // ... // token 有效期默认1天 'user.apiTokenExpire' => 1*24*3600, ];
到这里呢,客户端登录 服务端返回token给客户端就完成了。
按照文中一开始的分析,客户端应该把获取到的token存到本地,比如cookie中。以后再需要token校验的接口访问中,从本地读取比如从cookie中读取并访问接口即可。
根据token请求用户的认证操作
假设我们已经把获取到的token保存起来了,我们再以访问用户信息的接口为例。
yii\filters\auth\QueryParamAuth类认定的token参数是 access-token,我们可以在行为中修改下
public function behaviors()
{
return ArrayHelper::merge (parent::behaviors(), [
'authenticator' => [
'class' => QueryParamAuth::className(),
'tokenParam' => 'token',
'optional' => [
'login',
'signup-test'
],
]
] );
}
这里将默认的access-token修改为token。
Yii2中的场景(scenario)和验证规则(rule)详解Yii2的rule用于对模型属性进行验证,scenario用户定义不同场景下需要验证的模型,下面这篇文章主要给大家介绍了关于
浅谈使用 Yii2 AssetBundle 中 $publishOptions 的正确姿势本篇文章主要介绍了浅谈使用 Yii2 AssetBundle 中 $publishOptions 的正确姿势,具有一定的参考价值,感兴趣的小伙伴们可以
Yii2中组件的注册与创建方法这篇文章主要介绍了Yii2之组件的注册与创建的实现方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下
Yii2使用驼峰命名的形式访问控制器的示例代码这篇文章主要介绍了Yii2使用驼峰命名的形式访问控制器的实现方法,非常不错,具有参考借鉴价值,需要的朋友可以参
Yii2使用驼峰命名的形式访问控制器(实例讲解)下面小编就为大家带来一篇Yii2使用驼峰命名的形式访问控制器(实例讲解)。小编觉得挺不错的,现在就分享给大家,
Yii2.0实现生成二维码功能实例这篇文章主要介绍了Yii2.0实现生成二维码功能,结合实例形式分析了Yii2.0框架生成二维码所涉及的相关扩展引入步骤与