refactor(out): remove BaseAuth token parsing dependency

Made-with: Cursor
This commit is contained in:
apple
2026-04-29 17:06:55 +08:00
parent c7dfc79f1d
commit bbeb8bc6b6
3 changed files with 134 additions and 15 deletions

View File

@@ -0,0 +1,94 @@
<?php
// +----------------------------------------------------------------------
// | Author: ScottPan Team
// +----------------------------------------------------------------------
namespace app\services\auth;
use crmeb\exceptions\AuthException;
use crmeb\services\CacheService;
use crmeb\utils\ApiErrorCode;
use crmeb\utils\JwtAuth;
use Firebase\JWT\ExpiredException;
/**
* 本项目自有 access token 服务,不依赖 CRMEB 商业授权基础类。
*/
class AccessTokenService
{
/**
* 创建 access token并写入对应类型的 token bucket。
*/
public function createToken(int $id, string $type, string $authHash, array $extra = []): array
{
/** @var JwtAuth $jwtAuth */
$jwtAuth = app()->make(JwtAuth::class);
return $jwtAuth->createToken($id, $type, $extra + ['auth' => $authHash]);
}
/**
* 解析并校验 access token。
*
* @param callable $resolver 根据 token 内的 id 读取账号模型或数组
* @param callable $authHashResolver 根据账号返回当前有效的 auth hash
* @return mixed
* @throws \Psr\SimpleCache\InvalidArgumentException
*/
public function parseToken(string $token, string $type, callable $resolver, callable $authHashResolver)
{
if (!$token || $token === 'undefined') {
throw new AuthException(ApiErrorCode::ERR_LOGIN);
}
/** @var JwtAuth $jwtAuth */
$jwtAuth = app()->make(JwtAuth::class);
[$id, $tokenType, $auth] = $jwtAuth->parseToken($token);
if (!$id || $tokenType !== $type) {
throw new AuthException(ApiErrorCode::ERR_LOGIN_INVALID);
}
$md5Token = md5($token);
$cacheToken = CacheService::redisHandler($type)->get($md5Token, null);
if (!$cacheToken) {
throw new AuthException(ApiErrorCode::ERR_LOGIN);
}
if (isset($cacheToken['invalidNum']) && $cacheToken['invalidNum'] >= 3) {
$this->clearToken($md5Token, $type);
throw new AuthException(ApiErrorCode::ERR_LOGIN_INVALID);
}
try {
$jwtAuth->verifyToken();
CacheService::setTokenBucket($md5Token, $cacheToken, $cacheToken['exp'] ?? null, $type);
} catch (ExpiredException $e) {
$cacheToken['invalidNum'] = ($cacheToken['invalidNum'] ?? 0) + 1;
CacheService::setTokenBucket($md5Token, $cacheToken, $cacheToken['exp'] ?? null, $type);
throw new AuthException(ApiErrorCode::ERR_LOGIN);
} catch (\Throwable $e) {
$this->clearToken($md5Token, $type);
throw new AuthException(ApiErrorCode::ERR_LOGIN_INVALID);
}
$account = $resolver($id);
if (!$account) {
$this->clearToken($md5Token, $type);
throw new AuthException(ApiErrorCode::ERR_LOGIN);
}
if ($auth !== $authHashResolver($account)) {
throw new AuthException(ApiErrorCode::ERR_LOGIN_INVALID);
}
return $account;
}
protected function clearToken(string $md5Token, string $type): void
{
if (!request()->isCli()) {
CacheService::redisHandler($type)->delete($md5Token);
}
}
}