yii2 RESTful 接口 api -3 : 账户验证 和 速度控制

1.

创建数据库表:

sql创建:

CREATE TABLE IF NOT EXISTS `user` (  
  `id` int(20) unsigned NOT NULL AUTO_INCREMENT,  
  `username` varchar(50) DEFAULT NULL COMMENT '用户名',  
  `password_hash` varchar(80) DEFAULT NULL COMMENT '密码',  
  `password_reset_token` varchar(60) DEFAULT NULL COMMENT '密码token',  
  `email` varchar(60) DEFAULT NULL COMMENT '邮箱',  
  `auth_key` varchar(60) DEFAULT NULL,  
  `status` int(5) DEFAULT NULL COMMENT '状态',  
  `created_at` int(18) DEFAULT NULL COMMENT '创建时间',  
  `updated_at` int(18) DEFAULT NULL COMMENT '更新时间',  
  `password` varchar(50) DEFAULT NULL COMMENT '密码',  
  `role` varchar(50) DEFAULT NULL COMMENT 'role',  
  `access_token` varchar(60) DEFAULT NULL,  
  `allowance` int(20) NOT NULL,  
  `allowance_updated_at` int(20) NOT NULL,  
  PRIMARY KEY (`id`),  
  UNIQUE KEY `username` (`username`),  
  UNIQUE KEY `access_token` (`access_token`)  
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;  
  
--  
-- 转存表中的数据 `user`  
--  
  
INSERT INTO `user` (`id`, `username`, `password_hash`, `password_reset_token`, `email`, `auth_key`, `status`, `created_at`, `updated_at`, `password`, `role`, `access_token`, `allowance`, `allowance_updated_at`) VALUES  
(1, 'terry', '$2y$13$EyK1HyJtv4A/19Jb8gB5y.4SQm5y93eMeHjUf35ryLyd2dWPJlh8y', NULL, 'zqy234@126.com', 'pBJi3hyFsLsTuvUM9paFpWjYRatn3qwS', 10, 1441763620, 1447318986, NULL, NULL, 'xxxxxxxxxxxxxxxxxxxx', 0, 1447318986),  
(2, 'terry1', '$2y$13$B0P2T4wEFrxeecSEClo5g.wrapMqG0RmsSL0cJluHJ747M3R0vkMG', NULL, 'zqy2341@126.com', 'wIvJk7dMm6PQ1dJFz8iUqJ1RfH6rsDTW', 10, 1441763906, 1441763906, NULL, NULL, NULL, 0, 0),  
(3, 'zqy', '$2y$13$kcczJRoLGqSWHo7AZloCyeJiMYeM5SA1uXhyUZCNkFirWJuWeC3gO', NULL, 'zqy23114@126.com', 'K-76pcy7gxceemxRI2IeN5g1EhLMaCj8', 10, 1442544183, 1442544183, NULL, 'moderator', NULL, 0, 0),  
(4, 'admin', '$2y$13$w4/PWXvwRUKNSrDTSMhPhOnvxw4v4WWt7GVl2siozPDlmEjP04vJC', NULL, 'zqy2342321@126.com', 'hZWOaamjHEsPtuJJVghFRdE2oTj7Qv8P', 10, 1446524232, 1446524232, NULL, NULL, NULL, 0, 0);  

2.

设置用户组件 yii\web\User ;

'user' => [  
            'identityClass' => 'myapp\code\core\Erp\User\models\User',  
        #   'enableAutoLogin' => true,  
        ],

3.创建User模块,在模块中加入

'user' =>   
        [  
            'class' => 'myapp\code\core\Erp\User\Module',  
        ]

4.编辑 myapp\code\core\Erp\User\Module.php

<?php  
namespace myapp\code\core\Erp\User;  
use Yii;  
class Module extends \yii\base\Module  
{  
    public $controllerNamespace = 'myapp\code\core\Erp\User\controllers';  
  
    public function init()  
    {  
        parent::init();  
        # session 设置无效  
         \Yii::$app->user->enableSession = false;  
         \Yii::$app->user->loginUrl = null;  
        # 加载配置文件  
        if(file_exists(__DIR__ . '/etc/config.php')){  
            Yii::configure($this, ['params'=>(require(__DIR__ . '/etc/config.php'))]);  
        }  
        $this->params['blockDir'] = str_replace("\\controllers","",$this->controllerNamespace);  
    }  
}

主要是 设置:

\Yii::$app->user->enableSession = false;  
\Yii::$app->user->loginUrl = null;

 

5.创建  myapp\code\core\Erp\User\models\User 实现 yii\web\IdentityInterface 接口。

代码如下:

<?php  
namespace myapp\code\core\Erp\User\models;  
  
use Yii;  
use yii\base\NotSupportedException;  
use yii\behaviors\TimestampBehavior;  
use yii\db\ActiveRecord;  
use yii\web\IdentityInterface;  
use yii\filters\RateLimitInterface;  
/**  
 * User model  
 *  
 * @property integer $id  
 * @property string $username  
 * @property string $password_hash  
 * @property string $password_reset_token  
 * @property string $email  
 * @property string $auth_key  
 * @property integer $status  
 * @property integer $created_at  
 * @property integer $updated_at  
 * @property string $password write-only password  
 */  
class User extends ActiveRecord implements IdentityInterface ,RateLimitInterface  
{  
    const STATUS_DELETED = 0;  
    const STATUS_ACTIVE = 10;  
  
      
    # 速度控制  6秒内访问3次,注意,数组的第一个不要设置1,设置1会出问题,一定要  
    #大于2,譬如下面  6秒内只能访问三次  
    # 文档标注:返回允许的请求的最大数目及时间,例如,[100, 600] 表示在600秒内最多100次的API调用。  
    public  function getRateLimit($request, $action){  
         return [3, 6];  
    }  
    # 文档标注: 返回剩余的允许的请求和相应的UNIX时间戳数 当最后一次速率限制检查时。  
    public  function loadAllowance($request, $action){  
        //return [1,strtotime(date("Y-m-d H:i:s"))];  
        //echo $this->allowance;exit;  
         return [$this->allowance, $this->allowance_updated_at];  
    }  
    # allowance 对应user 表的allowance字段  int类型  
    # allowance_updated_at 对应user allowance_updated_at  int类型  
    # 文档标注:保存允许剩余的请求数和当前的UNIX时间戳。  
    public  function saveAllowance($request, $action, $allowance, $timestamp){  
        $this->allowance = $allowance;  
        $this->allowance_updated_at = $timestamp;  
        $this->save();  
    }  
      
      
      
    /**  
     * @inheritdoc  
     */  
    # 设置table  
    public static function tableName()  
    {  
        return 'user';  
    }  
  
    /**  
     * @inheritdoc  
     */  
    public function behaviors()  
    {  
        return [  
            TimestampBehavior::className(),  
        ];  
    }  
  
    /**  
     * @inheritdoc  
     */  
    # 设置 status  默认  ,以及取值的区间  
    public function rules()  
    {  
        return [  
            ['status', 'default', 'value' => self::STATUS_ACTIVE],  
            ['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],  
        ];  
    }  
  
    /**  
     * @inheritdoc  
     */  
    # 通过id 找到identity  
    public static function findIdentity($id)  
    {  
        return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);  
    }  
  
    /**  
     * @inheritdoc  
     */  
    # 通过access_token 找到identity  
    public static function findIdentityByAccessToken($token, $type = null)  
    {  
        return static::findOne(['access_token' => $token, 'status' => self::STATUS_ACTIVE]);  
    }  
    # 生成access_token  
    public function generateAccessToken()  
    {  
        $this->access_token = Yii::$app->security->generateRandomString();  
    }  
  
    /**  
     * Finds user by username  
     *  
     * @param string $username  
     * @return static|null  
     */  
    public static function findByUsername($username)  
    {  
        return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]);  
    }  
  
    /**  
     * Finds user by password reset token  
     *  
     * @param string $token password reset token  
     * @return static|null  
     */  
    # 此处是忘记密码所使用的  
    public static function findByPasswordResetToken($token)  
    {  
        if (!static::isPasswordResetTokenValid($token)) {  
            return null;  
        }  
  
        return static::findOne([  
            'password_reset_token' => $token,  
            'status' => self::STATUS_ACTIVE,  
        ]);  
    }  
  
    /**  
     * Finds out if password reset token is valid  
     *  
     * @param string $token password reset token  
     * @return boolean  
     */  
    public static function isPasswordResetTokenValid($token)  
    {  
        if (empty($token)) {  
            return false;  
        }  
  
        $timestamp = (int) substr($token, strrpos($token, '_') + 1);  
        $expire = Yii::$app->params['user.passwordResetTokenExpire'];  
        return $timestamp + $expire >= time();  
    }  
  
    /**  
     * @inheritdoc  
     */  
    public function getId()  
    {  
        return $this->getPrimaryKey();  
    }  
  
    /**  
     * @inheritdoc  
     */  
    public function getAuthKey()  
    {  
        return $this->auth_key;  
    }  
  
    /**  
     * @inheritdoc  
     */  
    public function validateAuthKey($authKey)  
    {  
        return $this->getAuthKey() === $authKey;  
    }  
  
    /**  
     * Validates password  
     *  
     * @param string $password password to validate  
     * @return boolean if password provided is valid for current user  
     */  
    public function validatePassword($password)  
    {  
        return Yii::$app->security->validatePassword($password, $this->password_hash);  
    }  
  
    /**  
     * Generates password hash from password and sets it to the model  
     *  
     * @param string $password  
     */  
    public function setPassword($password)  
    {  
        $this->password_hash = Yii::$app->security->generatePasswordHash($password);  
    }  
  
    /**  
     * Generates "remember me" authentication key  
     */  
    public function generateAuthKey()  
    {  
        $this->auth_key = Yii::$app->security->generateRandomString();  
    }  
  
    /**  
     * Generates new password reset token  
     */  
    public function generatePasswordResetToken()  
    {  
        $this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();  
    }  
  
    /**  
     * Removes password reset token  
     */  
    public function removePasswordResetToken()  
    {  
        $this->password_reset_token = null;  
    }  
}

6.控制器:

<?php  
namespace myapp\code\core\Erp\User\controllers;  
  
use Yii;  
use yii\web\Controller;  
use myapp\code\core\Erp\User\models\User;  
use yii\filters\auth\CompositeAuth;  
use yii\filters\auth\HttpBasicAuth;  
use yii\filters\auth\HttpBearerAuth;  
use yii\filters\auth\QueryParamAuth;  
use yii\filters\RateLimiter;  
class IndexController extends Controller  
{  
     
    public function init(){  
            parent::init();  
    }  
      
    # 行为 添加   
    #   验证 :authenticator  
    #   速度控制:rateLimiter  
    public function behaviors()  
    {  
        $behaviors = parent::behaviors();  
        $behaviors['authenticator'] = [  
            'class' => CompositeAuth::className(),  
            'authMethods' => [  
                # 下面是三种验证access_token方式  
                //HttpBasicAuth::className(),  
                //HttpBearerAuth::className(),  
                # 这是GET参数验证的方式  
                # http://10.10.10.252:600/user/index/index?access-token=xxxxxxxxxxxxxxxxxxxx  
                QueryParamAuth::className(),  
            ],  
          
        ];  
          
        # rate limit部分,速度的设置是在  
        #   \myapp\code\core\Erp\User\models\User::getRateLimit($request, $action){  
        /*  官方文档:  
            当速率限制被激活,默认情况下每个响应将包含以下HTTP头发送 目前的速率限制信息:  
            X-Rate-Limit-Limit: 同一个时间段所允许的请求的最大数目;  
            X-Rate-Limit-Remaining: 在当前时间段内剩余的请求的数量;  
            X-Rate-Limit-Reset: 为了得到最大请求数所等待的秒数。  
            你可以禁用这些头信息通过配置 yii\filters\RateLimiter::enableRateLimitHeaders 为false, 就像在上面的代码示例所示。  
  
        */  
        $behaviors['rateLimiter'] = [  
            'class' => RateLimiter::className(),  
            'enableRateLimitHeaders' => true,  
        ];  
        return $behaviors;  
    }  
      
     public function actionIndex()  
    {  
          
        echo Yii::$app->user->id;  
    }  
      
      
}

 

7

然后通过访问:

http://10.10.10.252:900/user/index/index?access-token=nnnnnnnnnnnnnn

就可以访问了,由于我设置的是6秒内访问3次,正常访问,查看head消息头:如下

我设置的是:6秒内最多访问3次的返回结果

X-Rate-Limit-Limit : 3        总次数还剩余3次

X-Rate-Limit-Remaining:2  还剩余2次

《yii2 RESTful 接口 api -3 : 账户验证 和 速度控制》有1个想法

发表评论

电子邮件地址不会被公开。 必填项已用*标注