ApiAgentBak.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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\TokenUtil;
  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 ApiAgentBak implements MiddlewareInterface
  23. {
  24. // 日志模块名称
  25. const LOG_MODULE = 'ApiAgent-Middleware-Log';
  26. const LOG_ACTION = 'verifyToken';
  27. const PROJECT = 'Api';
  28. /**
  29. * @var ContainerInterface
  30. */
  31. protected $container;
  32. /**
  33. * @var RequestInterface
  34. */
  35. protected $request;
  36. /**
  37. * @var HttpResponse
  38. */
  39. protected $response;
  40. protected $action;
  41. public function __construct(ContainerInterface $container, HttpResponse $response, RequestInterface $request)
  42. {
  43. $this->container = $container;
  44. $this->response = $response;
  45. $this->request = $request;
  46. }
  47. public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
  48. {
  49. //日志统一写入
  50. LogUtil::getInstance(self::PROJECT . "/");//设置日志存入通道
  51. Coroutine::defer(function () {
  52. LogUtil::close();//协程结束后统一写入
  53. });
  54. $this->action = $action = ActionUtil::actions($request);
  55. // 记录用户请求参数
  56. LogUtil::info('请求参数', $action['controller'], $action['action'], $this->request->all());
  57. //接口限流,写到中间件中
  58. if (!RedisUtil::getInstance(RedisKeyEnum::API_REQUEST_TRAFFIC)->requestLimit("{$action['controller']}/{$action['action']}", 1, 10)) {
  59. LogUtil::info('请求次数过多', $action['controller'], $action['action']);
  60. return $this->response206();
  61. }
  62. $token = $this->request->header('Access-Token');
  63. if (!empty($token) && !in_array("{$action['controller']}/{$action['action']}", self::tokenWhiteList())) {
  64. LogUtil::info('token 验证开始', self::LOG_MODULE, self::LOG_ACTION, (string)$token);
  65. //设置一个假token 用于测试
  66. if(strpos($token,'testuid_') !== false){
  67. $user_id = intval(substr($token,8));
  68. } else {
  69. // 校验token
  70. if (!$user_id = $this->checkToken($token)){
  71. return $this->response400();
  72. }
  73. }
  74. // 查询并记录用户信息
  75. $user = (new UserModel())->authUserInfo((int)$user_id);
  76. if (!$user) {
  77. //防止在缓存后操作得用户登录重试,清除缓存
  78. $system = new SystemService();
  79. $system->flushCache((int)$user_id);
  80. LogUtil::warning('账号不存在', self::LOG_MODULE, self::LOG_ACTION, ['user_id', $user_id]);
  81. return $this->response400();
  82. }
  83. LogUtil::info('用户编号', $action['controller'], $action['action'], $user_id);
  84. AuthUser::getInstance()->set(json_decode(json_encode($user), true));
  85. }
  86. return $handler->handle($request);
  87. }
  88. /**
  89. * 校验token
  90. *
  91. * @param string $token
  92. * @return false
  93. */
  94. public function checkToken(string $token)
  95. {
  96. $checkToken = TokenUtil::verifyToken($token);
  97. if (!$checkToken) {
  98. LogUtil::warning('token 验证失败', self::LOG_MODULE, self::LOG_ACTION, $checkToken);
  99. return false;
  100. }
  101. //签发时间大于当前服务器时间验证失败
  102. if (!isset($checkToken['iat']) || $checkToken['iat'] > time()) {
  103. LogUtil::warning('token 未生效', self::LOG_MODULE, self::LOG_ACTION, $checkToken);
  104. return false;
  105. }
  106. //过期时间小于当前服务器时间验证失败
  107. if (!isset($checkToken['exp']) || $checkToken['exp'] < time()) {
  108. LogUtil::warning('token 已失效', self::LOG_MODULE, self::LOG_ACTION, $checkToken);
  109. return false;
  110. }
  111. //验证参数信息
  112. if (empty($checkToken['data']['user_id'])) {
  113. LogUtil::warning('token 参数不全', self::LOG_MODULE, self::LOG_ACTION, $checkToken);
  114. return false;
  115. }
  116. return $checkToken['data']['user_id'];
  117. }
  118. /**
  119. * 令牌失效
  120. *
  121. * @param string $message
  122. * @param $result
  123. * @return ResponseInterface
  124. */
  125. private function response400(string $message = '令牌失效,请稍后重试!', $result = null): ResponseInterface
  126. {
  127. // 记录令牌校验
  128. $action = $this->action;
  129. LogUtil::info($message, $action['controller'], $action['action'], $result);
  130. return AppResult::response400($message, $result);
  131. }
  132. /**
  133. * 请求频繁
  134. *
  135. * @param string $message
  136. * @param $result
  137. * @return ResponseInterface
  138. */
  139. private function response206(string $message = '当前访问人数过多,请稍后再试!', $result = null): ResponseInterface
  140. {
  141. // 记录令牌校验
  142. $action = $this->action;
  143. LogUtil::info($message, $action['controller'], $action['action'], $result);
  144. return AppResult::response206($message, $result);
  145. }
  146. /**
  147. * token校验黑名单
  148. * @return string[]
  149. */
  150. public function tokenWhiteList(): array
  151. {
  152. return [
  153. 'v1/Common/PassportController/login',
  154. 'v1/Common/PassportController/wxLogin',
  155. ];
  156. }
  157. }