之前写过一篇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. VS2015调试UWP程序时提示错误DEP0700 : Registration of the app failed. Another user has already installed

    在同一台windows10电脑上调试过一个工程以后,切换了账号再次调试出现错误 DEP0700 : Registration of the app failed. Another user has a ...

  2. js组件之间的通信

    应用场景: 1.在刷微博的时候,滑到某个头像上,会出现一张usercard(用户名片), 微博列表区有这个usercard, 推荐列表也有这个usercard,评论区也有. 2.在网上购物时,购物车安 ...

  3. AngularJS是什么

    先标明来源: https://code.angularjs.org/1.3.15/docs/guide/introduction 也就是官网针对1.3.15版的说明 What Is Angular? ...

  4. python基础整理笔记(八)

    一. python反射的方式来调用方法属性 反射主要指的就是hasattr.getattr.setattr.delattr这四个函数,作用分别是检查是否含有某成员.获取成员.设置成员.删除成员. 此外 ...

  5. middleware中间件的概念

    简要来说express就是一个由路由和中间件构成的 web 开发框架. 当express服务收到客户端的请求时,会通过一组函数来处理请求. 这些函数用于解析请求体数据,处理错误,或者负责返回各种情况对 ...

  6. angular文件引入带来的绑定问题

    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script ...

  7. vim中输入tab符

    今天在写Makefile时各种出错.后来发现是all:的下一行,make前面必须是tab符,不能是空格. 但是vim中只要按tab就会自动转换成4个空格.平时编程需要,也不便把这个设置取消. 查了下, ...

  8. listView后面加控件,防止被挤

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  9. html5 localStorage实现表单本地存储

    随笔开头,我不得不吐槽,为什么我的随笔每次发布之后,都会在分分钟之内移出首页.好气啊!! 进入正题了,项目中有许多表单输入框要填写,还有一些单选复选框之类的.用户可能在填写了大量的信息之后,不小心刷新 ...

  10. 利用nodejs实现登录并转码视频(原创)

    nodejs的出现让前端人员可以使用js打造后台,也许哪天就真的摆脱了对java或者php的依赖了. 今天跟大家分享一个利用nodejs接受前端post请求,并实现视频转码的这样一个例子.视频转码用到 ...