فهرست منبع

fix: 修复token不失效

runphp 1 ماه پیش
والد
کامیت
d21d2310e5
2فایلهای تغییر یافته به همراه46 افزوده شده و 17 حذف شده
  1. 20 13
      src/Auth.php
  2. 26 4
      src/Hook/AuthHook.php

+ 20 - 13
src/Auth.php

@@ -18,14 +18,16 @@ class Auth implements AuthInterface
 
     public const int SLEEP_WAY = 60;
 
-    private array $config;
+    private static array $config;
 
     public function __construct(private readonly UserTypeEnum $userType)
     {
-        $this->config = [
-            'jwt_secret' => env('JWT_SECRET', ''),
-            'expire_in' => env('JWT_EXPIRE_IN', 3600),
-        ];
+        if (empty(self::$config)) {
+            self::$config = [
+                'jwt_secret' => env('JWT_SECRET', ''),
+                'expire_in' => (int) env('JWT_EXPIRE_IN', 3600),
+            ];
+        }
     }
 
     public function refreshToken(string $jwt): string
@@ -38,12 +40,14 @@ class Auth implements AuthInterface
         $payload = [
             'iss' => 'SixShop', // 签发者
             'aud' => $this->userType->value, // 接收者
-            'sub' => encrypt_data($userId, $this->config['jwt_secret']), // 主题
-            'exp' => time() + $this->config['expire_in'], // 过期时间
+            'sub' => encrypt_data($userId, self::$config['jwt_secret']), // 主题
+            'exp' => time() + self::$config['expire_in'], // 过期时间
             'iat' => time(), // 签发时间
             'jti' => Uuid::uuid4()->toString(), // 唯一标识
         ];
-        return JWT::encode($payload, $this->config['jwt_secret'], self::ALGORITHM);
+        $jwt = JWT::encode($payload, self::$config['jwt_secret'], self::ALGORITHM);
+        Event::trigger('token_generate', (object)$payload);
+        return $jwt;
     }
 
     /**
@@ -53,14 +57,14 @@ class Auth implements AuthInterface
     {
         JWT::$leeway = self::SLEEP_WAY;
         try {
-            $payload = JWT::decode($jwt, new Key($this->config['jwt_secret'], self::ALGORITHM));
+            $payload = JWT::decode($jwt, new Key(self::$config['jwt_secret'], self::ALGORITHM));
         } catch (ExpiredException $e) {
             // ... 忽略
             $payload = $e->getPayload();
         }
 
         $res = match (UserTypeEnum::tryFrom($payload->aud)) {
-            $this->userType => decrypt_data($payload->sub, $this->config['jwt_secret']),
+            $this->userType => decrypt_data($payload->sub, self::$config['jwt_secret']),
             default => throw new \Exception('token 类型错误'),
         };
         Event::trigger('token_verify', $payload);
@@ -71,12 +75,10 @@ class Auth implements AuthInterface
     {
         JWT::$leeway = self::SLEEP_WAY;
         try {
-            $payload = JWT::decode($jwt, new Key($this->config['jwt_secret'], self::ALGORITHM));
+            $payload = JWT::decode($jwt, new Key(self::$config['jwt_secret'], self::ALGORITHM));
         } catch (ExpiredException $e) {
             // ... 忽略
             $payload = $e->getPayload();
-        } catch (\Exception) {
-            return;
         }
         Event::trigger('token_revoke', $payload);
     }
@@ -85,4 +87,9 @@ class Auth implements AuthInterface
     {
         return $this->userType;
     }
+
+    public static function getConfig(): array
+    {
+        return self::$config;
+    }
 }

+ 26 - 4
src/Hook/AuthHook.php

@@ -13,23 +13,34 @@ class AuthHook
 {
     public const string TOKEN_REVOKE = 'token_revoke:';
 
+    private int $expireIn;
+
     public function __construct(private Cache $cache)
     {
+        $this->expireIn = Auth::getConfig()['expire_in'];
+    }
+
+    #[Hook("token_generate")]
+    public function generateToken($payload): void
+    {
+        $this->renewToken($payload);
     }
 
     /**
-     * @throws \Exception
+     * @throws \ExpiredException
      */
     #[Hook("token_verify")]
     public function checkToken($payload): void
     {
         if ($this->cache->has(self::TOKEN_REVOKE . $payload->jti)
-            && $this->cache->get(self::TOKEN_REVOKE . $payload->jti) > time() + Auth::SLEEP_WAY) {
+            && $this->cache->get(self::TOKEN_REVOKE . $payload->jti) > time() - Auth::SLEEP_WAY) {
+            // 未过期可以续期
+            $this->renewToken($payload);
             return;
         }
         $ex = new ExpiredException('Expired token');
-        $ex->setPayload($payload->exp);
-        $ex->setTimestamp($timestamp);
+        $ex->setPayload($payload);
+        $ex->setTimestamp($payload->exp);
         throw $ex;
     }
 
@@ -38,4 +49,15 @@ class AuthHook
     {
         $this->cache->remember(self::TOKEN_REVOKE . $payload->jti, time(), $payload->exp - time() + Auth::SLEEP_WAY);
     }
+
+    /**
+     * @param $payload
+     * @return void
+     * @throws \Throwable
+     */
+    public function renewToken($payload): void
+    {
+        $exp = time() + $this->expireIn;
+        $this->cache->remember(self::TOKEN_REVOKE . $payload->jti, $exp, $this->expireIn + Auth::SLEEP_WAY);
+    }
 }