之前寫過一篇Yii2框架制作RESTful風(fēng)格的API快速入門教程,今天接著來探究一下Yii2 RESTful的格式化響應(yīng),授權(quán)認(rèn)證和速率限制三個(gè)部分
一、目錄結(jié)構(gòu)
先列出需要改動(dòng)的文件。目錄如下:
web├─ common│ └─ models │ └ User.php└─ frontend├─ config│ └ main.php└─ controllers└ BookController.php
二、格式化響應(yīng)
Yii2 RESTful支持JSON和XML格式,如果想指定返回?cái)?shù)據(jù)的格式,需要配置yii/filters/ContentNegotiator::formats屬性。例如,要返回JSON格式,修改frontend/controllers/BookController.php,加入紅色標(biāo)記代碼:
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中支持被響應(yīng)格式名稱。
三、授權(quán)認(rèn)證
RESTful APIs通常是無狀態(tài)的,因此每個(gè)請(qǐng)求應(yīng)附帶某種授權(quán)憑證,即每個(gè)請(qǐng)求都發(fā)送一個(gè)access token來認(rèn)證用戶。
1.配置user應(yīng)用組件(不是必要的,但是推薦配置):
設(shè)置yii/web/User::enableSession屬性為false(因?yàn)镽ESTful APIs為無狀態(tài)的,當(dāng)yii/web/User::enableSession為false,請(qǐng)求中的用戶認(rèn)證狀態(tài)就不能通過session來保持)
設(shè)置yii/web/User::loginUrl屬性為null(顯示一個(gè)HTTP 403 錯(cuò)誤而不是跳轉(zhuǎn)到登錄界面)
具體方法,修改frontend/config/main.php,加入紅色標(biāo)記代碼:
'components' => [...'user' => ['identityClass' => 'common/models/User','enableAutoLogin' => true,'enableSession' => false,'loginUrl' => null,],...]
2.在控制器類中配置authenticator行為來指定使用哪種認(rèn)證方式,修改frontend/controllers/BookController.php,加入紅色標(biāo)記代碼:
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' => [/*下面是三種驗(yàn)證access_token方式*///1.HTTP 基本認(rèn)證: access token 當(dāng)作用戶名發(fā)送,應(yīng)用在access token可安全存在API使用端的場景,例如,API使用端是運(yùn)行在一臺(tái)服務(wù)器上的程序。//HttpBasicAuth::className(),//2.OAuth 2: 使用者從認(rèn)證服務(wù)器上獲取基于OAuth2協(xié)議的access token,然后通過 HTTP Bearer Tokens 發(fā)送到API 服務(wù)器。//HttpBearerAuth::className(),//3.請(qǐng)求參數(shù): access token 當(dāng)作API URL請(qǐng)求參數(shù)發(fā)送,這種方式應(yīng)主要用于JSONP請(qǐng)求,因?yàn)樗荒苁褂肏TTP頭來發(fā)送access token//http://localhost/user/index/index?access-token=123QueryParamAuth::className(),],];$behaviors['contentNegotiator']['formats']['text/html'] = Response::FORMAT_JSON;return $behaviors;}}3.創(chuàng)建一張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 '0' COMMENT '狀態(tài)',`created_at` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '創(chuàng)建時(shí)間',`updated_at` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新時(shí)間',`access_token` varchar(50) NOT NULL DEFAULT '' COMMENT 'restful請(qǐng)求token',`allowance` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'restful剩余的允許的請(qǐng)求數(shù)',`allowance_updated_at` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'restful請(qǐng)求的UNIX時(shí)間戳數(shù)',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 ('1', 'admin', '$2y$13$1KWwchqGvxDeORDt5pRW.OJarf06PjNYxe2vEGVs7e5amD3wnEX.i', '', '', 'z3sM2KZvXdk6mNXXrz25D3JoZlGXoJMC', '10', '1478686493', '1478686493', '123', '4', '1478686493');
在common/models/User.php類中實(shí)現(xiàn) yii/web/IdentityInterface::findIdentityByAccessToken()方法。修改common/models/User.php,加入紅色標(biāo)記代碼::
public static function findIdentityByAccessToken($token, $type = null){//findIdentityByAccessToken()方法的實(shí)現(xiàn)是系統(tǒng)定義的//例如,一個(gè)簡單的場景,當(dāng)每個(gè)用戶只有一個(gè)access token, 可存儲(chǔ)access token 到user表的access_token列中, 方法可在User類中簡單實(shí)現(xiàn),如下所示:return static::findOne(['access_token' => $token]);//throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');}四、速率限制
為防止濫用,可以增加速率限制。例如,限制每個(gè)用戶的API的使用是在60秒內(nèi)最多10次的API調(diào)用,如果一個(gè)用戶同一個(gè)時(shí)間段內(nèi)太多的請(qǐng)求被接收,將返回響應(yīng)狀態(tài)代碼 429 (這意味著過多的請(qǐng)求)。
1.Yii會(huì)自動(dòng)使用yii/filters/RateLimiter為yii/rest/Controller配置一個(gè)行為過濾器來執(zhí)行速率限制檢查。如果速度超出限制,該速率限制器將拋出一個(gè)yii/web/TooManyRequestsHttpException。
修改frontend/controllers/BookController.php,加入紅色標(biāo)記代碼:
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' => [/*下面是三種驗(yàn)證access_token方式*///1.HTTP 基本認(rèn)證: access token 當(dāng)作用戶名發(fā)送,應(yīng)用在access token可安全存在API使用端的場景,例如,API使用端是運(yùn)行在一臺(tái)服務(wù)器上的程序。//HttpBasicAuth::className(),//2.OAuth 2: 使用者從認(rèn)證服務(wù)器上獲取基于OAuth2協(xié)議的access token,然后通過 HTTP Bearer Tokens 發(fā)送到API 服務(wù)器。//HttpBearerAuth::className(),//3.請(qǐng)求參數(shù): access token 當(dāng)作API URL請(qǐng)求參數(shù)發(fā)送,這種方式應(yīng)主要用于JSONP請(qǐng)求,因?yàn)樗荒苁褂肏TTP頭來發(fā)送access token//http://localhost/user/index/index?access-token=123QueryParamAuth::className(),],];$behaviors['contentNegotiator']['formats']['text/html'] = Response::FORMAT_JSON;return $behaviors;}}2.在user表中使用兩列來記錄容差和時(shí)間戳信息。為了提高性能,可以考慮使用緩存或NoSQL存儲(chǔ)這些信息。
修改common/models/User.php,加入紅色標(biāo)記代碼:
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{....// 返回在單位時(shí)間內(nèi)允許的請(qǐng)求的最大數(shù)目,例如,[10, 60] 表示在60秒內(nèi)最多請(qǐng)求10次。public function getRateLimit($request, $action){return [5, 10];}// 返回剩余的允許的請(qǐng)求數(shù)。public function loadAllowance($request, $action){return [$this->allowance, $this->allowance_updated_at];}// 保存請(qǐng)求時(shí)的UNIX時(shí)間戳。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()方法的實(shí)現(xiàn)是系統(tǒng)定義的//例如,一個(gè)簡單的場景,當(dāng)每個(gè)用戶只有一個(gè)access token, 可存儲(chǔ)access token 到user表的access_token列中, 方法可在User類中簡單實(shí)現(xiàn),如下所示:return static::findOne(['access_token' => $token]);}....}以上所述是小編給大家介紹的Yii2框架RESTful API 格式化響應(yīng),授權(quán)認(rèn)證和速率限制三部分詳解 ,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)VeVb武林網(wǎng)網(wǎng)站的支持!
新聞熱點(diǎn)
疑難解答
圖片精選