// +---------------------------------------------------------------------- namespace app\services\system\admin; use app\dao\system\admin\AdminAuthDao; use app\services\BaseServices; use app\services\other\CacheServices; use app\services\supplier\SystemSupplierServices; use crmeb\exceptions\AuthException; use crmeb\services\CacheService; use crmeb\utils\ApiErrorCode; use crmeb\utils\JwtAuth; use Firebase\JWT\ExpiredException; use Psr\SimpleCache\InvalidArgumentException; use think\annotation\Inject; /** * admin授权service * Class AdminAuthServices * @package app\services\system\admin * @mixin AdminAuthDao */ class AdminAuthServices extends BaseServices { /** * @var AdminAuthDao */ #[Inject] protected AdminAuthDao $dao; /** * 获取Admin授权信息 * @param string $token * @return array * @throws InvalidArgumentException */ public function parseToken(string $token): array { /** @var CacheService $cacheService */ $cacheService = app()->make(CacheService::class); if (!$token || $token === 'undefined') { throw new AuthException(ApiErrorCode::ERR_LOGIN); } /** @var JwtAuth $jwtAuth */ $jwtAuth = app()->make(JwtAuth::class); //设置解析token [$id, $type, $auth] = $jwtAuth->parseToken($token); //检测token是否过期 $md5Token = md5($token); if (!$cacheService->hasToken($md5Token) || !($cacheToken = $cacheService->getTokenBucket($md5Token))) { $this->authFailAfter($id, $type); throw new AuthException(ApiErrorCode::ERR_LOGIN); } //是否超出有效次数 if (isset($cacheToken['invalidNum']) && $cacheToken['invalidNum'] >= 3) { if (!request()->isCli()) { $cacheService->clearToken($md5Token); } $this->authFailAfter($id, $type); throw new AuthException(ApiErrorCode::ERR_LOGIN_INVALID); } //验证token try { $jwtAuth->verifyToken(); $cacheService->setTokenBucket($md5Token, $cacheToken, $cacheToken['exp']); } catch (ExpiredException $e) { $cacheToken['invalidNum'] = isset($cacheToken['invalidNum']) ? $cacheToken['invalidNum']++ : 1; $cacheService->setTokenBucket($md5Token, $cacheToken, $cacheToken['exp']); } catch (\Throwable $e) { if (!request()->isCli()) { $cacheService->clearToken($md5Token); } $this->authFailAfter($id, $type); throw new AuthException(ApiErrorCode::ERR_LOGIN_INVALID); } //获取管理员信息 $adminInfo = $this->dao->get($id); if (!$adminInfo || !$adminInfo->id || $adminInfo->status == 0 || $adminInfo->is_del == 1) { if (!request()->isCli()) { $cacheService->clearToken($md5Token); } $this->authFailAfter($id, $type); throw new AuthException(ApiErrorCode::ERR_LOGIN_STATUS); } //修改密码后token立刻过期 if ($auth !== md5($adminInfo['pwd'])) { throw new AuthException(ApiErrorCode::ERR_LOGIN_STATUS); } if($adminInfo['admin_type'] == 4){ $adminInfo = app()->make(SystemSupplierServices::class)->getOne(['id' => (int)$adminInfo->relation_id, 'is_del' => 0], '*', ['admin']); if (!$adminInfo || !$adminInfo->account || $adminInfo->admin_is_del) { if (!request()->isCli()) { $cacheService->clearToken($md5Token); } throw new AuthException(ApiErrorCode::ERR_LOGIN_STATUS); } } $adminInfo->type = $type; return $adminInfo->hidden(['pwd', 'is_del', 'status'])->toArray(); } /** * token验证失败后事件 */ protected function authFailAfter($id, $type) { try { $postData = request()->post(); $rule = trim(strtolower(request()->rule()->getRule())); $method = trim(strtolower(request()->method())); //添加商品退出后事件 if ($rule === 'product/product/' && $method === 'post') { $this->saveProduct($id, $postData); } } catch (\Throwable $e) { } } /** * 保存提交数据 * @param $adminId * @param $postData */ protected function saveProduct($adminId, $postData) { /** @var CacheServices $cacheService */ $cacheService = app()->make(CacheServices::class); $cacheService->setDbCache($adminId . '_product_data', $postData, 68400); } }