DriverAgent.php 5.9 KB

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