ikaras / yii2-oauth2-rest-template
Yii2 Rest API 模板,带有 OAuth2(完全配置的 filsh/yii2-oauth2-server 扩展)
Requires
- php: >=5.4.0
- filsh/yii2-oauth2-server: 2.0.0
- yiisoft/yii2: *
This package is not auto-updated.
Last update: 2024-09-25 15:42:00 UTC
README
这是一个配置了 OAuth2 服务器的 Yii2 Rest 应用模板(使用 https://github.com/Filsh/yii2-oauth2-server)。解决了 OAuth2 服务器扩展的适配问题,按照官方指南中的建议构建了带有版本号的目录结构,增加了一些现成功能以加快开发。
您可以使用此模板作为创建服务 API 端的起点。
在 Docker 上运行
为了快速测试代码,我创建了这个https://github.com/ikaras/yii2-oauth2-rest-docker - 它使用 Docker Compose 启动 LEMP 堆栈,并带有所有需要的配置,准备好接收请求。只需遵循其中的说明。
安装
通过 Composer 安装
如果您没有 Composer,您可以按照 getcomposer.org 上的说明 安装它。
然后,您可以使用以下命令安装应用程序
composer global require "fxp/composer-asset-plugin:~1.1.1"
composer create-project --stability="dev" --prefer-source ikaras/yii2-oauth2-rest-template .
配置
- 配置您的 Web 服务器,例如 Nginx 或 Apache(参见这里),查看
application/api/www
目录。我在测试中使用了域名api.loc
。 - 在
application/api/config/common.php
中更改到您的数据库连接 - 运行迁移
php application/api/yiic migrate --migrationPath=@yii/rbac/migrations --interactive=0 \
php application/api/yiic migrate --migrationPath=@vendor/filsh/yii2-oauth2-server/migrations --interactive=0 \
php application/api/yiic migrate --interactive=0 \
php application/api/yiic migrate --interactive=0 \
结构
\application # root folder for environment (frontend, backend, api, etc.)
\api # here is code for build REST API with OAuth2 server
| \common # common controllers and models for versions
| | \controllers # for tests created only one ProductController
| | \models # and one model Product
| \components # global for API components (parents for project's controllers, models, filters)
| |-APIModule.php # parent for all module/versions
| |-ActiveController.php # child of yii's rest ActiveController, parent for all ones in project
| |-Controller.php # child of yii's rest Controller
| | \db # contain parents for all project's ActiveRecord and ActiveQuery
| | \filters
| | | -OAuth2AccessFilter.php # MAIN IMPROVEMENT: analyze action publicity and scopes to attach filter
| | | # to authorize by access token
| | \traits # contain ControllersCommonTrait.php with configuration of filters, used in both rest controllers
| \config
| \migrations # contain migrations for create users table, filling demo products and scopes
| \models # have User model
| \versions # directory for versions, each version is module as recommend in official yii2 guide
| | \v1 # created for test 1st version with childs of ProductController and Product model
| \www # public directory, containt index.php
测试
条件
- 域名:
api.loc
(如果您不想使用虚拟主机,也可以使用类似https:///TestOAuth2/application/api/www/index.php/
的内容) - 版本:
v1
- API 点:
/products
、/products/<id>
、/products/custom
、/products/protected
- 用户: 登录:
admin@api.loc
,密码:123123123
- 作用域: 默认(默认作用域,CO :))、自定义、受保护 - 用于访问到 /products/custom 和 /products/protected 点
描述
为了测试,创建了 active rest controller ProductController 来管理 Product 模型。
此控制器具有以下访问规则(以 yii2 格式)
public function accessRules()
{
return [
['allow' => true, 'roles' => ['?']],
[
'allow' => true,
'actions' => ['view','create','update','delete'],
'roles' => ['@'],
],
[
'allow' => true,
'actions' => ['custom'],
'roles' => ['@'],
'scopes' => ['custom'],
],
[
'allow' => true,
'actions' => ['protected'],
'roles' => ['@'],
'scopes' => ['protected'],
]
];
}
API 中的每个控制器都可以用自己自己的访问规则覆盖方法 accessRules
。规则可以包含额外的属性 - scope,这意味着访问令牌应该有额外的权限。
因此,从规则中我们可以理解到
- 控制器中所有操作都是开放的(请求可以没有访问令牌),但是
- 操作
view
、create
、update
、delete
- 仅对授权用户可用 - 并且对于操作
custom
和protected
需要额外的作用域
测试请求
1. 请求公开 API 点
curl -i -H "Accept:application/json" -H "Content-Type:application/json" "http://api.loc/v1/products"
2. 请求获取访问令牌
curl -i -H "Accept:application/json" -H "Content-Type:application/json" "http://api.loc/oauth2/token" -XPOST \
-d '{"grant_type":"password","username":"admin@api.loc","password":"123123123","client_id":"testclient","client_secret":"testpass"}'
3. 请求获取带有作用域的访问令牌
curl -i -H "Accept:application/json" -H "Content-Type:application/json" "http://api.loc/oauth2/token" -XPOST \
-d '{"grant_type":"password","username":"admin@api.loc","password":"123123123","client_id":"testclient","client_secret":"testpass","scope":"custom"}'
4. 请求受保护的API点
curl -i -H "Accept:application/json" -H "Content-Type:application/json" \
"http://api.loc/v1/products/1?access_token=76f4c0d40347f24a73799335cefb495be9ea364b"
已经完成了什么?
- 获取了Yii2框架并创建了通用目录结构(见结构部分)。
- 使用官方手册配置Yii2为RESTful Web服务。
- 为项目中的所有组件创建了父类以进行继承(保存在
components
目录中)。更多信息请参阅结构部分。类Controller和ActiveController是所有使用相同特质的控制器的父类。ControllersCommonTrait - 它连接(重定义)所有需要的过滤器到控制器的动作。 - 目录
common
包含每个版本通用的控制器和模型。 - 然后我附加并配置了Filsh的Yii2 OAuth2扩展,其基于广泛使用的PHP OAuth2服务器库。所有详细信息您可以在这些仓库中找到。我已经配置了以下内容
- 在common配置中配置模块
oauth2
; - 修改方法User::findIdentityByAccessToken,使用
oauth2
模块通过令牌授权用户。
- 开发了OAuth2AccessFilter,并用它替换了标准的Yii2 AccessFilter(在ControllersCommonTrait中,所有控制器)以更方便地使用Scopes。关于它将在下面说明。
Scopes
如官方OAuth2库文档所述
在OAuth2应用程序中使用Scope对于适当的权限控制通常是关键的。Scope用于限制资源所有者授予客户端的授权。最常见的用途是Facebook允许用户授权客户端执行各种不同的功能(“访问基本信息”,“在墙上发布”等)。
因此,每个令牌都可以有特定的权限来运行相应的API点。在我们的案例中,API点是动作。
在Yii2中,我们已经有了一个工具可以根据用户角色控制特定动作的访问,所以我决定扩展其功能以定义动作的Scopes。
因此,创建了OAuth2AccessFilter,它复制(不是继承,结构不允许继承)了标准AccessFilter的逻辑,并使用额外的逻辑处理由oauth2
模块处理的私有动作的Scopes。
因此,如果用户的角色允许他运行动作(API点),则将检查用户的令牌是否具有执行该动作所需的Scopes(如果动作已定义有限的Scopes)。使用示例可以在ProductController中找到,这意味着只有授权的用户,其令牌包含custom
范围,才能访问custom
动作。