ThinkPHP中的接口的安全防护措施小结

93 阅读4分钟

这篇文章主要为大家详细介绍了一些在 ThinkPHP 中对接口进行防护的措施,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

目录

**

GPT4.0+Midjourney绘画+国内大模型 会员永久免费使用!
【 如果你想靠AI翻身,你先需要一个靠谱的工具!  】

1. 身份验证

令牌验证

对于需要访问的接口,用户或客户端在请求时需要提供一个有效的令牌(Token)。可以使用 JWT(JSON Web Token)来实现。在用户登录成功后,服务器为用户生成一个包含用户信息和过期时间的 JWT,并返回给用户。用户在后续的请求中,将 JWT 放在请求头中,如 Authorization: Bearer <token>

``

````// 在控制器中验证 JWT`

`use` `Firebase\JWT\JWT;`

`use` `Firebase\JWT\Key;`

`class` ` ApiController  ``extends` `Controller`

`{`

`    ``public` `function` `index()`

`    ``{`

`        ``$token` `= request()->header(``'Authorization'``);`

`        ``if` `(!``$token``) {`

`            ``return` `json([``'error'` ` =>  ``'Token not provided'``], 401);`

`        ``}`

`        ``try` `{`

`            ``$token` ` =  ``str_replace``(``'Bearer '`` ,  ``''`` ,  ``$token``);`

`            ``$decoded` `= JWT::decode(``$token`` ,  ``new` `Key(``'your_secret_key'`` ,  ``'HS256'``));`

`            ``// 进行后续操作`

`        `` }  ``catch` ` (\Exception  ``$e``) {`

`            ``return` `json([``'error'` ` =>  ``'Invalid token'``], 401);`

`        ``}`

`    ``}`

`}`

解释:

  • 首先,通过 request()->header('Authorization') 获取请求头中的 Authorization 字段。
  • 如果没有该字段,返回 401 错误。
  • 去掉 Bearer 前缀后,使用 JWT 的 decode 方法结合你的 secret_key 和加密算法 HS256 来解码令牌。
  • 解码成功则继续后续操作,解码失败则返回 401 错误。

API Key 验证

为每个客户端分配一个唯一的 API Key,在请求时需要将 API Key 作为参数或者请求头的一部分传递。服务器根据存储的 API Key 列表进行验证。

``

````class` ` ApiController  ``extends` `Controller`

`{`

`    ``public` `function` `index()`

`    ``{`

`        ``$apiKey` `= request()->header(``'X-API-KEY'``);`

`        ``if` `(!``$apiKey` `||!in_array(``$apiKey``, [``'valid_key1'`` ,  ``'valid_key2'``])) {`

`            ``return` `json([``'error'` ` =>  ``'Invalid API Key'``], 403);`

`        ``}`

`        ``// 进行后续操作`

`    ``}`

`}`

解释:

  • 从请求头的 X-API-KEY 中获取 API Key。
  • 检查 API Key 是否在预定义的有效列表中,不在则返回 403 错误。

2. 输入验证

使用验证器

对于接口接收的参数,使用 ThinkPHP 的验证器对其进行严格的验证,确保输入符合预期。

``


```js
````namespace` `app\api\validate;`

`use` `think\Validate;`

`class` ` UserValidate  ``extends` `Validate`

`{`

`    ``protected` `$rule` `= [`

`        ``'username'` ` =>  ``'require|max:25'``,`

`        ``'age'` ` =>  ``'number|between:1,120'``,`

`    ``];`

`}`

`// 在控制器中使用验证器`

`class` ` UserController  ``extends` `Controller`

`{`

`    ``public` `function` `save()`

`    ``{`

`        ``$validate` ` =  ``new` `UserValidate();`

`        ``$data` `= request()->post();`

`        ``if` `(!``$validate``->check(``$data``)) {`

`            ``return` `json([``'error'` ` =>  ``$validate``->getError()], 422);`

`        ``}`

`        ``// 数据有效,进行后续操作`

`    ``}`

`}`


解释:

  • 定义 UserValidate 验证器,设置 username 必须存在且最大长度为 25,age 为数字且在 1 到 120 之间。
  • 在控制器中,使用该验证器检查 request()->post() 的数据,不符合规则则返回 422 错误

3. 权限控制

基于角色的访问控制(RBAC)  :

为不同的用户或客户端分配不同的角色(如管理员、普通用户等),并根据角色来决定其对接口的访问权限。

``


```js
````class` ` ApiController  ``extends` `Controller`

`{`

`    ``public` `function` `index()`

`    ``{`

`        ``$userRole` `= session(``'user_role'``);`

`        ``if` `(``$userRole``!==``'admin'``) {`

`            ``return` `json([``'error'` ` =>  ``'Permission denied'``], 403);`

`        ``}`

`        ``// 允许访问的操作`

`    ``}`

`}`

``

```js

解释:

  • 通过 session('user_role') 获取用户角色。
  • 若不是管理员角色,返回 403 错误。

4. 防止 CSRF 攻击

对于非 GET 请求的接口

虽然接口通常是无状态的,但对于某些特殊情况,可使用 CSRF 令牌进行防护。可以采用和普通表单类似的 CSRF 令牌机制。

``

````<``form` `action``=``"/api/action"` `method``=``"post"``>`

`    ``{:token()}`

`    ``<``input` `type``=``"submit"` `value``=``"Submit"``>`

`</``form``>`



在控制器中:

``


```js
````class` ` ApiController  ``extends` `Controller`

`{`

`    ``public` `function` `index()`

`    ``{`

`        ``$token` `= input(``'__token__'``);`

`        ``if` `(!``$token` `||!check_token(``$token``)) {`

`            ``return` `json([``'error'` ` =>  ``'Invalid CSRF token'``], 403);`

`        ``}`

`        ``// 继续操作`

`    ``}`

`}`



解释:

  • 首先,在表单中使用 {:token()} 生成 CSRF 令牌。
  • 在控制器中,使用 input('__token__') 获取提交的令牌,通过 check_token 函数检查其有效性,无效则返回 403 错误。

5. 数据加密

传输加密

使用 HTTPS 协议来加密客户端和服务器之间的通信,确保数据在传输过程中的安全性。可以通过服务器配置启用 HTTPS。

敏感数据加密

对于接口中涉及的敏感数据,如用户密码、信用卡信息等,在存储和传输过程中使用加密算法进行加密

``


```js
``````````use` `think\facade\Crypt;``$encryptedData` `= Crypt::encrypt(``'sensitive_data'`` ,  ``'your_secret_key'``);``$decryptedData` `= Crypt::decrypt(``$encryptedData`` ,  ``'your_secret_key'``);` |
| -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


解释:

  • 使用 Crypt 类对数据进行加密,使用 your_secret_key 作为密钥。
  • 解密时,使用相同的密钥进行解密操作。

6. 频率限制

使用中间件

对某些接口设置请求频率限制,防止恶意用户的频繁请求,可以使用中间件来实现。

``


```js
````namespace` `app\http\middleware;`

`use` `think\facade\Cache;`

`class` `RateLimitMiddleware`

`{`

`    ``public` `function` `handle(``$request`` , \Closure  ``$next``)`

`    ``{`

`        ``$key` ` =  ``$request`` ->ip().  ``$request``->path();`

`        ``$count` `= Cache::get(``$key``, 0);`

`        ``if` `(``$count` `>= 10) {`

`            ``return` `json([``'error'` ` =>  ``'Too many requests'``], 429);`

`        ``}`

`        ``Cache::inc(``$key``);`

`        ``Cache::expire(``$key`` , 60);  ``// 1分钟内最多请求 10 次`

`        ``return` `$next``(``$request``);`

`    ``}`



解释:

  • 通过 request()->ip() 和 request()->path() 生成唯一的键。
  • 从缓存中获取该键的请求计数,若超过 10 次则返回 429 错误。
  • 每次请求,计数器加 1,并设置 1 分钟的过期时间。

7. 日志记录和监控

记录异常请求

对于可能存在风险的请求,如验证失败、异常错误等,使用日志记录功能,以便后续分析和监控。

``


```js
````use` `think\facade\Log;`

`class` ` ApiController  ``extends` `Controller`

`{`

`    ``public` `function` `index()`

`    ``{`

`        ``try` `{`

`            ``// 业务逻辑`

`        `` }  ``catch` ` (\Exception  ``$e``) {`

`            ``Log::error(``'Error occurred in API: '`` .  ``$e``->getMessage());`

`            ``return` `json([``'error'` ` =>  ``'Internal error'``], 500);`

`        ``}`

`    ``}`

`}`




解释:

当发生异常时,使用 Log::error 记录错误信息,并返回 500 错误。

8. 输出过滤

防止 XSS 攻击

对于接口输出的数据,使用 htmlspecialchars 或 htmlentities 进行转义,防止 XSS 攻击


```js
````$output` ` =  ``'<script>alert("XSS");</script>'``;`

`$safeOutput` `= htmlspecialchars(``$output``);`


解释:

将可能导致 XSS 攻击的代码片段使用 htmlspecialchars 进行转义,确保输出的安全性。

通过以上多种措施,可以在 ThinkPHP 中对接口进行较为全面的防护,确保接口的安全性和可靠性。

到此这篇关于ThinkPHP中的接口的安全防护措施小结的文章就介绍到这了