之前写过一篇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. Spring学习笔记 5. 尚硅谷_佟刚_Spring_自动装配

    1,回顾以前的做法 一个人有姓名,有住址,有一辆车.其中住址和车也是一个类,这种情况下不用自动装配是十分容易实现的 (1)Person类 package com.zsq; public class P ...

  2. Winpcap安装,Cannot open include file 'pcap.h'

    VC报错 fatal error C1083: Cannot open include file: 'pcap.h': No such file or directory Winpcap是window ...

  3. String.Format格式说明——复制于DotNet笔记

    String.Format格式说明   C#格式化数值结果表 字符 说明 示例 输出 C 货币 string.Format("{0:C3}", 2) $2.000 D 十进制 st ...

  4. 在c++这片神秘的大陆上

    在c++这片神秘的大陆上,有一个无往而不利的地下王国,据说其手段血腥残忍,却深得民心,因为,他们是侠,是剑胆琴心,诗肠酒骨的侠客,他们不知解决了多少疑难杂症,除去了多少问题漏洞,而他们的首领-> ...

  5. MATLAB常用操作

    1.点乘,点除,点乘方 点乘(对应元素相乘),必须同维或者其中一个是标量,a.*b 点除,a.\b表示矩阵b的每个元素除以a中对应元素或者除以常数a,a./b表示常数a除以矩阵b中每个元素或者矩阵a除 ...

  6. android开发学习之Layer List

    Android中drawable分为Bitmap File.Nine-Patch File.Layer List.State List.Level List.Transition Drawable.I ...

  7. Linux之DNS

    DNS服务器配置 一.DNS概述:DNS 是域名系统 (Domain Name System) 的缩写,是一种组织域层次结构的计算机和网络服务命名系统.它的作用是:把域名转换成为网络可以识别的 IP ...

  8. [UDP] UDP 报文数据(CoAP protocol)

    UDP 机器控制项目 协议报文格式: Ver +                  T       +     TKL + Code + MessageID + 11111111 + Command ...

  9. Replication的犄角旮旯(一)--变更订阅端表名的应用场景

    <Replication的犄角旮旯>系列导读 Replication的犄角旮旯(一)--变更订阅端表名的应用场景 Replication的犄角旮旯(二)--寻找订阅端丢失的记录 Repli ...

  10. 微软再次要求Google审查官方链接 称将进行调查

    之前代表微软向Google发出DMCA删除通知的反盗版公司再次要求Google审查Microsoft.com官网链接.微软对此表示将进行调查,已经要求反盗版公司停止以微软的名义发出DMCA通知. 仅仅 ...