ApiAgent.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Middleware;
  4. use App\Master\Enum\RedisKeyEnum;
  5. use App\Model\Arts\UserModel;
  6. use App\Service\SystemService;
  7. use App\Utils\AppResult;
  8. use App\Utils\Control\ActionUtil;
  9. use App\Utils\Control\AuthUser;
  10. use App\Utils\Encrypt\TokenFast;
  11. use App\Utils\LogUtil;
  12. use App\Utils\RedisUtil;
  13. use Hyperf\Coroutine\Coroutine;
  14. use Hyperf\HttpServer\Contract\RequestInterface;
  15. use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
  16. use Hyperf\HttpServer\Router\Dispatched;
  17. use Psr\Container\ContainerInterface;
  18. use Psr\Http\Message\ResponseInterface;
  19. use Psr\Http\Message\ServerRequestInterface;
  20. use Psr\Http\Server\MiddlewareInterface;
  21. use Psr\Http\Server\RequestHandlerInterface;
  22. class ApiAgent implements MiddlewareInterface
  23. {
  24. const PROJECT = 'Api';
  25. /**
  26. * @var ContainerInterface
  27. */
  28. protected $container;
  29. /**
  30. * @var RequestInterface
  31. */
  32. protected $request;
  33. /**
  34. * @var HttpResponse
  35. */
  36. protected $response;
  37. protected $action;
  38. public function __construct(ContainerInterface $container, HttpResponse $response, RequestInterface $request)
  39. {
  40. $this->container = $container;
  41. $this->response = $response;
  42. $this->request = $request;
  43. }
  44. public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
  45. {
  46. //日志统一写入
  47. LogUtil::getInstance(self::PROJECT . "/");//设置日志存入通道
  48. Coroutine::defer(function () {
  49. LogUtil::close();// 协程结束后统一写入
  50. });
  51. $this->action = ActionUtil::getInstance()->actions($request,self::PROJECT);
  52. $params = $this->request->all();
  53. // 记录用户请求参数
  54. LogUtil::info('请求参数', $this->action['controller'], $this->action['action'], $params);
  55. //接口限流,写到中间件中
  56. if (!RedisUtil::getInstance(RedisKeyEnum::API_REQUEST_TRAFFIC)->requestLimit("{$this->action['controller']}/{$this->action['action']}", 1, 10)) {
  57. LogUtil::info('请求次数过多', $this->action['controller'], $this->action['action']);
  58. return $this->response206();
  59. }
  60. $token = $this->request->header('token');
  61. if (empty($token)) $token = $params['token'] ?? '';
  62. if (!empty($token) && !in_array("{$this->action['controller']}/{$this->action['action']}", self::tokenWhiteList())) {
  63. LogUtil::info('token 验证开始', $this->action['controller'], $this->action['action'], (string)$token);
  64. // 校验token
  65. if (!$user_id = $this->checkToken($token)){
  66. return $this->response401();
  67. }
  68. // 查询并记录用户信息
  69. $user = (new UserModel())->authUserInfo($user_id);
  70. if (!$user) {
  71. LogUtil::warning('账号不存在', $this->action['controller'], $this->action['action'], ['user_id', $user_id]);
  72. return $this->response401();
  73. }
  74. LogUtil::info('用户编号', $this->action['controller'], $this->action['action'], $user_id);
  75. AuthUser::getInstance()->set(json_decode(json_encode($user), true));
  76. }
  77. return $handler->handle($request);
  78. }
  79. /**
  80. * 校验token
  81. *
  82. * @param string $token
  83. * @return false|int
  84. */
  85. public function checkToken(string $token): false|int
  86. {
  87. $checkToken = TokenFast::get($token);
  88. if (!$checkToken) {
  89. LogUtil::warning('token 验证失败', $this->action['controller'], $this->action['action'], $checkToken);
  90. return false;
  91. }
  92. //验证参数信息
  93. if (empty($checkToken['user_id'])) {
  94. LogUtil::warning('token 参数不全', $this->action['controller'], $this->action['action'], $checkToken);
  95. return false;
  96. }
  97. return (int)$checkToken['user_id'];
  98. }
  99. /**
  100. * 令牌失效
  101. *
  102. * @param string $message
  103. * @param $result
  104. * @return ResponseInterface
  105. */
  106. private function response401(string $message = '令牌失效,请稍后重试!', $result = null): ResponseInterface
  107. {
  108. // 记录令牌校验
  109. LogUtil::info($message, $this->action['controller'], $this->action['action'], $result);
  110. return AppResult::response_fast(401,$message, $result);
  111. }
  112. /**
  113. * 请求频繁
  114. *
  115. * @param string $message
  116. * @param $result
  117. * @return ResponseInterface
  118. */
  119. private function response206(string $message = '当前访问人数过多,请稍后再试!', $result = null): ResponseInterface
  120. {
  121. // 记录令牌校验
  122. LogUtil::info($message, $this->action['controller'], $this->action['action'], $result);
  123. return AppResult::response_fast(206,$message, $result);
  124. }
  125. /**
  126. * token校验黑名单
  127. * @return string[]
  128. */
  129. public function tokenWhiteList(): array
  130. {
  131. return [
  132. 'v1/UserController/login',
  133. ];
  134. }
  135. }