翼度科技»论坛 编程开发 PHP 查看内容

PHP转Go系列 | ThinkPHP与Gin框架之OpenApi授权设计实践

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
大家好,我是码农先森。
我之前待过一个做 ToB 业务的公司,主要是研发以会员为中心的 SaaS 平台,其中涉及的子系统有会员系统、积分系统、营销系统等。在这个 SaaS 平台中有一个重要的角色「租户」,这个租户可以拥有一个或多个子系统的使用权限,此外租户还可以使用平台所提供的开放 API 「即 OpenApi」来获取相关系统的数据。有了 OpenApi 租户可以更便捷的与租户自有系统进行打通,提高系统之间数据的传输效率。那么这一次实践的主要内容是 OpenApi 的授权设计,希望对大家能有所帮助。

我们先梳理一下本次实践的关键步骤:

  • 给每一个租户分配一对 AppKey、AppSecret。
  • 租户通过传递 AppKey、AppSecret 参数获取到平台颁发的 AccessToken。
  • 租户再通过 AccessToken 来换取可以实际调用 API 的 RefreshToken。
  • 这时的 RefreshToken 是具有时效性,目前设置的有效期为 2 个小时。
  • 针对 RefreshToken 还会提供一个刷新时效的接口。
  • 只有 RefreshToken 才有调用业务 API 的真实权限。
有些朋友对 AccessToken 和 RefreshToken 傻傻分不清,疑问重重?我在最开始接触这个设计的时候也是懵逼的,为啥要搞两个,一个不也能解决问题吗?确实搞一个也可以用,但大家如果对接过微信的开放 API 就会发现他们也是有两个,此外还有很多大的开放平台也是采用类似的设计逻辑,所以存在即合理。
这里我说一下具体的原因,AccessToken 是基于 AppKey 和 AppSecret 来生成的,而 RefreshToken 是通过 AccessToken 交换得来的。并且 RefreshToken 具备有效性,需要通过一个刷新接口,不定时的刷新 RefreshToken。RefreshToken 的使用是最频繁的,在每次的业务 API 调用是都需要进行传输,传输的次数多了那么 RefreshToken 被劫持的风险就会变大。假设 RefreshToken 真的被泄露,那么损失也是控制在 2 个小时以内,为了减低损失也还可以调低有效时间。总而言之,网络的传输并不总是能保证安全,AccessToken 在网络上只需要一次传输「即换取 RefreshToken」,而 RefreshToken 需要不断的在网络的传输「即不断调用业务 API」,传输的次数越少风险就越低,这就是设计两个 Token 的根本原因。
话不多说,开整!
按照惯例,我们先对整个目录结构进行梳理。这次的重点逻辑主要是在控制器 controller 的 auth 中实现,包含三个 API 接口一是生成 AccessToken、二是通过 AccessToken 交换 RefreshToken,三是刷新 RefreshToken。中间件 middleware 的 api_auth 是对 RefreshToken 进行解码验证,判断客户端传递的 RefreshToken 是否有效。此外,AccessToken 和 RefreshToken 的生成策略都是采用的 JWT 规则。
  1. [manongsen@root php_to_go]$ tree -L 2
  2. .
  3. ├── go_openapi
  4. │   ├── app
  5. │   │   ├── controller
  6. │   │   │   ├── auth.go
  7. │   │   │   └── user.go
  8. │   │   ├── middleware
  9. │   │   │   └── api_auth.go
  10. │   │   ├── model
  11. │   │   │   └── tenant.go
  12. │   │   ├── config
  13. │   │   │   └── config.go
  14. │   │   └── route.go
  15. │   ├── go.mod
  16. │   ├── go.sum
  17. │   └── main.go
  18. └── php_openapi
  19. │   ├── app
  20. │   │   ├── controller
  21. │   │   │   ├── Auth.php
  22. │   │   │   └── User.php
  23. │   │   ├── middleware
  24. │   │   │   └── ApiAuth.php
  25. │   │   ├── model
  26. │   │   │   └── Tenant.php
  27. │   │   └── middleware.php
  28. │   ├── composer.json
  29. │   ├── composer.lock
  30. │   ├── config
  31. │   ├── route
  32. │   │   └── app.php
  33. │   ├── think
  34. │   ├── vendor
  35. │   └── .env
复制代码
ThinkPHP

使用 composer 创建 php_openapi 项目,并且安装 predis、php-jwt 扩展包。
  1. [manongsen@root ~]$ pwd
  2. /home/manongsen/workspace/php_to_go/php_openapi
  3. [manongsen@root php_openapi]$ composer create-project topthink/think php_openapi
  4. [manongsen@root php_openapi]$ cp .example.env .env
  5. [manongsen@root php_openapi]$ composer require predis/predis
  6. [manongsen@root php_openapi]$ composer require firebase/php-jwt
复制代码
使用 ThinkPHP 框架提供的命令行工具 php think 创建控制器、中间件、模型文件。
  1. [manongsen@root php_openapi]$ php think make:model Tenant
  2. Model:app\model\Tenant created successfully.
  3. [manongsen@root php_openapi]$ php think make:controller Auth
  4. Controller:app\controller\Auth created successfully.
  5. [manongsen@root php_openapi]$ php think make:controller User
  6. Controller:app\controller\User created successfully.
  7. [manongsen@root php_openapi]$ php think make:middleware ApiAuth
  8. Middleware:app\middleware\ApiAuth created successfully.
复制代码
在 route/app.php 文件中定义接口的路由。
[code]

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具