| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- <?php
- namespace app\admin\service;
- use app\admin\model\User;
- use think\facade\Cache;
- use think\facade\Config;
- use think\exception\RuntimeException;
- use thans\jwt\exception\JWTException;
- use thans\jwt\facade\JWT;
- class JwtService
- {
- /**
- * Token 过期时间(秒),优先读取 jwt 配置文件
- * @var int
- */
- private $exp;
- public function __construct()
- {
- // 从 thans/jwt 配置文件读取过期时间(config/jwt.php)
- $this->exp = Config::get('jwt.ttl', 7200);
- }
- /**
- * 生成 JWT Token(适配 thans/jwt)
- * @param User $user 用户模型实例
- * @return string
- * @throws RuntimeException
- */
- public function generateToken(User $user): string
- {
- // 严格校验参数类型
- if (!$user instanceof User) {
- throw new RuntimeException('生成Token失败:必须传入 User 模型实例');
- }
- try {
- // 构建 JWT 载荷(thans/jwt 支持数组格式)
- $payload = [
- 'sub' => $user->id, // 主题(用户ID)
- 'user_id' => $user->id, // 自定义字段:用户ID
- 'iat' => time(), // 签发时间
- 'exp' => time() + $this->exp, // 过期时间
- 'iss' => Config::get('app.app_name', 'admin_system'), // 签发者
- ];
- // 生成 Token(thans/jwt 核心方法)
- $token = JWT::builder($payload);
- // 缓存 Token(区分普通用户/商家)
- $cacheKey = $user->is_store == 0
- ? "user_{$user->id}_jwt"
- : "store_{$user->id}_jwt";
- // TP 缓存:set 方法存储,过期时间与 Token 一致
- Cache::set($cacheKey, $token, $this->exp);
- return $token;
- } catch (JWTException $e) {
- throw new RuntimeException('生成JWT Token失败:'.$e->getMessage());
- }
- }
- /**
- * 验证 JWT Token 有效性(适配 thans/jwt)
- * @param string $token JWT Token 字符串(支持带/不带 Bearer 前缀)
- * @return array|null 解码后的载荷数组(无效返回null)
- */
- public function validateToken(string $token): ?array
- {
- // 预处理 Token:移除 Bearer 前缀
- $token = trim(str_replace('Bearer ', '', $token));
- if (empty($token)) {
- return null;
- }
- try {
- // 验证并解码 Token(thans/jwt 核心方法)
- $payload = JWT::verify($token);
- // 额外校验:缓存中的 Token 是否一致(防止注销/伪造)
- if (isset($payload['user_id'])) {
- $user = User::find($payload['user_id']);
- if ($user) {
- $cacheKey = $user->is_store == 0
- ? "user_{$user->id}_jwt"
- : "store_{$user->id}_jwt";
- $cacheToken = Cache::get($cacheKey);
- // 缓存无 Token 或不一致,视为无效
- if ($cacheToken !== $token) {
- return null;
- }
- }
- }
- return (array)$payload;
- } catch (JWTException $e) {
- // 捕获 thans/jwt 专属异常(过期、签名错误、格式错误等)
- return null;
- }
- }
- /**
- * 注销 Token(清除缓存)
- * @param User $user 用户模型实例
- * @return bool
- */
- public function invalidateToken(User $user): bool
- {
- $cacheKey = $user->is_store == 0
- ? "user_{$user->id}_jwt"
- : "store_{$user->id}_jwt";
- return Cache::delete($cacheKey);
- }
- /**
- * 刷新 Token(续期,thans/jwt 内置支持)
- * @param string $oldToken 旧 Token
- * @return string|null 新 Token(无效返回null)
- */
- public function refreshToken(string $oldToken): ?string
- {
- $oldToken = trim(str_replace('Bearer ', '', $oldToken));
- if (empty($oldToken)) {
- return null;
- }
- try {
- // 验证旧 Token 并生成新 Token(自动续期)
- $newToken = JWT::refresh($oldToken);
- // 更新缓存中的 Token
- $payload = JWT::verify($oldToken);
- if (isset($payload['user_id'])) {
- $user = User::find($payload['user_id']);
- if ($user) {
- $cacheKey = $user->is_store == 0
- ? "user_{$user->id}_jwt"
- : "store_{$user->id}_jwt";
- Cache::set($cacheKey, $newToken, $this->exp);
- }
- }
- return $newToken;
- } catch (JWTException $e) {
- return null;
- }
- }
- }
|