之前写过一篇Yii2框架RESTful API教程(一) - 快速入门,今天接着来探究一下Yii2 RESTful的格式化响应,授权认证和速率限制三个部分

一、目录结构

先列出需要改动的文件。目录如下:

web
├─ common
│ └─ models
│ └ User.php
└─ frontend
├─ config
│ └ main.php
└─ controllers
└ BookController.php

二、格式化响应

Yii2 RESTful支持JSON和XML格式,如果想指定返回数据的格式,需要配置yii\filters\ContentNegotiator::formats属性。例如,要返回JSON格式,修改frontend/controllers/BookController.php,加入红色标记代码:

namespace frontend\controllers;

use yii\rest\ActiveController;
use yii\web\Response; class BookController extends ActiveController
{
public $modelClass = 'frontend\models\Book'; public function behaviors() {
$behaviors = parent::behaviors();
$behaviors['contentNegotiator']['formats']['text/html'] = Response::FORMAT_JSON;
return $behaviors;
}
}

返回XML格式:FORMAT_XML。formats属性的keys支持MIME类型,而values必须在yii\web\Response::formatters中支持被响应格式名称。

三、授权认证

RESTful APIs通常是无状态的,因此每个请求应附带某种授权凭证,即每个请求都发送一个access token来认证用户。

1.配置user应用组件(不是必要的,但是推荐配置):
  设置yii\web\User::enableSession属性为false(因为RESTful APIs为无状态的,当yii\web\User::enableSession为false,请求中的用户认证状态就不能通过session来保持)
  设置yii\web\User::loginUrl属性为null(显示一个HTTP 403 错误而不是跳转到登录界面)
具体方法,修改frontend/config/main.php,加入红色标记代码:

'components' => [
...
'user' => [
'identityClass' => 'common\models\User',
'enableAutoLogin' => true, 'enableSession' => false,
'loginUrl' => null, ],
...
]

2.在控制器类中配置authenticator行为来指定使用哪种认证方式,修改frontend/controllers/BookController.php,加入红色标记代码:

namespace frontend\controllers;

use yii\rest\ActiveController;
use yii\web\Response; use yii\filters\auth\CompositeAuth;
use yii\filters\auth\QueryParamAuth; class BookController extends ActiveController
{
public $modelClass = 'frontend\models\Book'; public function behaviors() {
$behaviors = parent::behaviors(); $behaviors['authenticator'] = [
'class' => CompositeAuth::className(),
'authMethods' => [
/*下面是三种验证access_token方式*/
//1.HTTP 基本认证: access token 当作用户名发送,应用在access token可安全存在API使用端的场景,例如,API使用端是运行在一台服务器上的程序。
//HttpBasicAuth::className(),
//2.OAuth 2: 使用者从认证服务器上获取基于OAuth2协议的access token,然后通过 HTTP Bearer Tokens 发送到API 服务器。
//HttpBearerAuth::className(),
//3.请求参数: access token 当作API URL请求参数发送,这种方式应主要用于JSONP请求,因为它不能使用HTTP头来发送access token
//http://localhost/user/index/index?access-token=123
QueryParamAuth::className(),
],
]; $behaviors['contentNegotiator']['formats']['text/html'] = Response::FORMAT_JSON;
return $behaviors;
}
}

3.创建一张user表

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL DEFAULT '' COMMENT '用户名',
`password_hash` varchar(100) NOT NULL DEFAULT '' COMMENT '密码',
`password_reset_token` varchar(50) NOT NULL DEFAULT '' COMMENT '密码token',
`email` varchar(20) NOT NULL DEFAULT '' COMMENT '邮箱',
`auth_key` varchar(50) NOT NULL DEFAULT '',
`status` tinyint(3) unsigned NOT NULL DEFAULT '' COMMENT '状态',
`created_at` int(10) unsigned NOT NULL DEFAULT '' COMMENT '创建时间',
`updated_at` int(10) unsigned NOT NULL DEFAULT '' COMMENT '更新时间',
`access_token` varchar(50) NOT NULL DEFAULT '' COMMENT 'restful请求token',
`allowance` int(10) unsigned NOT NULL DEFAULT '' COMMENT 'restful剩余的允许的请求数',
`allowance_updated_at` int(10) unsigned NOT NULL DEFAULT '' COMMENT 'restful请求的UNIX时间戳数',
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
UNIQUE KEY `access_token` (`access_token`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('', 'admin', '$2y$13$1KWwchqGvxDeORDt5pRW.OJarf06PjNYxe2vEGVs7e5amD3wnEX.i', '', '', 'z3sM2KZvXdk6mNXXrz25D3JoZlGXoJMC', '', '', '', '', '', '');

在common/models/User.php类中实现 yii\web\IdentityInterface::findIdentityByAccessToken()方法。修改common/models/User.php,加入红色标记代码::

public static function findIdentityByAccessToken($token, $type = null)
{
//findIdentityByAccessToken()方法的实现是系统定义的
//例如,一个简单的场景,当每个用户只有一个access token, 可存储access token 到user表的access_token列中, 方法可在User类中简单实现,如下所示:
return static::findOne(['access_token' => $token]);
//throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
}

四、速率限制

为防止滥用,可以增加速率限制。例如,限制每个用户的API的使用是在60秒内最多10次的API调用,如果一个用户同一个时间段内太多的请求被接收,将返回响应状态代码 429 (这意味着过多的请求)。

1.Yii会自动使用yii\filters\RateLimiter为yii\rest\Controller配置一个行为过滤器来执行速率限制检查。如果速度超出限制,该速率限制器将抛出一个yii\web\TooManyRequestsHttpException。
修改frontend/controllers/BookController.php,加入红色标记代码:

namespace frontend\controllers;

use yii\rest\ActiveController;
use yii\web\Response;
use yii\filters\auth\CompositeAuth;
use yii\filters\auth\QueryParamAuth; use yii\filters\RateLimiter; class BookController extends ActiveController
{
public $modelClass = 'frontend\models\Book'; public function behaviors() {
$behaviors = parent::behaviors(); $behaviors['rateLimiter'] = [
'class' => RateLimiter::className(),
'enableRateLimitHeaders' => true,
]; $behaviors['authenticator'] = [
'class' => CompositeAuth::className(),
'authMethods' => [
/*下面是三种验证access_token方式*/
//1.HTTP 基本认证: access token 当作用户名发送,应用在access token可安全存在API使用端的场景,例如,API使用端是运行在一台服务器上的程序。
//HttpBasicAuth::className(),
//2.OAuth 2: 使用者从认证服务器上获取基于OAuth2协议的access token,然后通过 HTTP Bearer Tokens 发送到API 服务器。
//HttpBearerAuth::className(),
//3.请求参数: access token 当作API URL请求参数发送,这种方式应主要用于JSONP请求,因为它不能使用HTTP头来发送access token
//http://localhost/user/index/index?access-token=123
QueryParamAuth::className(),
],
];
$behaviors['contentNegotiator']['formats']['text/html'] = Response::FORMAT_JSON;
return $behaviors;
}
}

2.在user表中使用两列来记录容差和时间戳信息。为了提高性能,可以考虑使用缓存或NoSQL存储这些信息。
修改common/models/User.php,加入红色标记代码:

namespace common\models;

use Yii;
use yii\base\NotSupportedException;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface; use yii\filters\RateLimitInterface; class User extends ActiveRecord implements IdentityInterface, RateLimitInterface
{ .... // 返回在单位时间内允许的请求的最大数目,例如,[10, 60] 表示在60秒内最多请求10次。
public function getRateLimit($request, $action)
{
return [5, 10];
} // 返回剩余的允许的请求数。
public function loadAllowance($request, $action)
{
return [$this->allowance, $this->allowance_updated_at];
} // 保存请求时的UNIX时间戳。
public function saveAllowance($request, $action, $allowance, $timestamp)
{
$this->allowance = $allowance;
$this->allowance_updated_at = $timestamp;
$this->save();
} .... public static function findIdentityByAccessToken($token, $type = null)
{
//throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
//findIdentityByAccessToken()方法的实现是系统定义的
//例如,一个简单的场景,当每个用户只有一个access token, 可存储access token 到user表的access_token列中, 方法可在User类中简单实现,如下所示:
return static::findOne(['access_token' => $token]);
} ....
}

PHP的RESTful实例: PHP实现RESTful风格的API实例

Yii2框架RESTful API教程(二) - 格式化响应,授权认证和速率限制的更多相关文章

  1. Yii2框架RESTful API教程(一) - 快速入门

    前不久做一个项目,是用Yii2框架写一套RESTful风格的API,就去查了下<Yii 2.0 权威指南 >,发现上面写得比较简略.所以就在这里写一篇教程贴,希望帮助刚接触Yii2框架RE ...

  2. Yii2框架RESTful API教程

    前不久做一个项目,是用Yii2框架写一套RESTful风格的API,就去查了下<Yii 2.0 权威指南 >,发现上面写得比较简略.所以就在这里写一篇教程贴,希望帮助刚接触Yii2框架RE ...

  3. Django编写RESTful API(二):请求和响应

    欢迎访问我的个人网站:www.comingnext.cn 前言 在上一篇文章,已经实现了访问指定URL就返回了指定的数据,这也体现了RESTful API的一个理念,每一个URL代表着一个资源.当然我 ...

  4. Yii2.0 RESTful API 之速率限制

    Yii2.0 RESTFul API 之速率限制 什么是速率限制? 权威指南翻译过来为限流,为防止滥用,你应该考虑对您的 API 限流. 例如,您可以限制每个用户 10 分钟内最多调用 API 100 ...

  5. Yii2.0 RESTful API 认证教程

    认证介绍 和Web应用不同,RESTful APIs 通常是无状态的, 也就意味着不应使用 sessions 或 cookies, 因此每个请求应附带某种授权凭证,因为用户授权状态可能没通过 sess ...

  6. 用 Flask 来写个轻博客 (33) — 使用 Flask-RESTful 来构建 RESTful API 之二

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 构建 RESTful Flask API 定义资源路由 格式 ...

  7. Yii2.0 RESTful API 基础配置教程

    创建api应用  通过拷贝原有的应用,重命名得到新的应用 安装完 Composer,运行下面的命令来安装 Composer Asset 插件: php composer.phar global req ...

  8. Yii2框架加入API Modules

    一.环境部署 1. read fucking Yii Documents. http://www.yiichina.com/doc/guide/2.0 2. 了解依赖注入模式 Java描写叙述: ht ...

  9. Yii2框架添加API Modules

    原文链接:http://www.itnose.net/detail/6459353.html : 一.环境部署 1. read fucking Yii Documents. http://www.yi ...

随机推荐

  1. gc roots 垃圾回收

    gc roots包括以下几个: 虚拟机栈(栈桢中的本地变量表)中的引用对象 方法区中的类静态属性引用的对象 方法区中的常量引用的对象 本地方法栈中JNI(即native方法)的引用的对象 java,c ...

  2. Spring绑定表单数据

    Spring提供了一些jsp页面常用的form标签,很大程度上提高了我们开发的速度,不用再一个个的标签去绑定属性,而且后台接收数据也很简单,可以直接接收object对象作为属性.官方form标签介绍的 ...

  3. Android中实现倒计时

    1.需求 弹出提示的dialog,实现倒计时,结束后关闭dialog 2.dialog界面布局 <?xml version="1.0" encoding="utf- ...

  4. centos 安装apache 和 php5.6

    centos 安装 php5.6,安装前需要先安装数据库和apache 安装 apache2.4 安装基础依赖:# yum install gcc gcc-c++ glibc glibc-devel ...

  5. iOS 开发-- enum与typeof enum用法

    一, 两者的用法 枚举类型定义用关键字enum标识,形式为: enum标识符 { 枚举数据表 }; enum用来定义一系列宏定义常量区别用,相当于一系列的#define ** **,当然它后面的标识符 ...

  6. 【leetcode】Merge Two Sorted Lists

    Merge two sorted linked lists and return it as a new list. The new list should be made by splicing t ...

  7. Bullet物理引擎在OpenGL中的应用

    Bullet物理引擎在OpenGL中的应用 在开发OpenGL的应用之时, 难免要遇到使用物理来模拟OpenGL中的场景内容. 由于OpenGL仅仅是一个关于图形的开发接口, 因此需要通过第三方库来实 ...

  8. Mroonga 3.0.8 发布,MySQL 存储引擎

    Mroonga 3.0.8 支持 REPAIR TABLE 支持损坏的 groonga 数据库. Mroonga 是一个 MySQL 存储引擎,基于 Groonga,提供完整的全文搜索引擎.

  9. 分享:根据webservice WSDL地址自动生成java调用代码及JAR包

    分享:根据webservice WSDL地址自动生成java调用代码及JAR包使用步骤:一.安装java 并配置JAVA_HOME 及 path二.安装ANT 并配置ANT_HOME三.解压WsdlT ...

  10. [教程]怎么用百度云观看和下载"磁力链接"无需下载直接观看.

    1, 打开网址 http://okbt.net/  输入你想要看的电影名字, 点搜索,鼠标右键点击拷贝磁力链接.或者 电脑装了迅雷的话.可以直接点击.用迅雷下载. 磁力链接都是这种格式的.例: mag ...