更新若干功能
This commit is contained in:
@@ -69,7 +69,11 @@ class JWTService
|
||||
$payload = [
|
||||
'iat' => $issuedAt,
|
||||
'exp' => $expirationTime,
|
||||
'data' => $data
|
||||
// sub 是标准声明,网关/旧客户端剥掉自定义 data 时还能靠它找回用户
|
||||
'sub' => (string) ($data['id'] ?? ''),
|
||||
// 与小程序 token(scope=wx)区分,两边共用 JWT_SECRET 但不能互认
|
||||
'scope' => 'admin',
|
||||
'data' => $data,
|
||||
];
|
||||
RedisService::getInstance()->init(config('nl.redis.jwt'))->set($data['id'], json_encode($data));
|
||||
return JWT::encode($payload, $this->secretKey, 'HS256');
|
||||
@@ -83,9 +87,14 @@ class JWTService
|
||||
public function parseToken(): ?object
|
||||
{
|
||||
try {
|
||||
if (empty($this->token)) return UtilsService::getInstance()->notAuth('请先登录');
|
||||
if (empty($this->token)) {
|
||||
return UtilsService::getInstance()->notAuth('请先登录');
|
||||
}
|
||||
return JWT::decode($this->token, new Key($this->secretKey, 'HS256'));
|
||||
} catch (Exception $e) {
|
||||
if ((int) $e->getCode() === 401) {
|
||||
throw $e;
|
||||
}
|
||||
return UtilsService::getInstance()->notAuth('【1】Token解析失败!请重新登录:'. $e->getMessage());
|
||||
}
|
||||
}
|
||||
@@ -100,14 +109,59 @@ class JWTService
|
||||
{
|
||||
try {
|
||||
$jwt = $this->parseToken();
|
||||
$user = RedisService::getInstance()->init(config('nl.redis.jwt'))->get($jwt->data->id);
|
||||
if (empty($user)) return UtilsService::getInstance()->notAuth('登录状态过期');
|
||||
return json_decode($user, true);
|
||||
} catch (Exception $e) {
|
||||
$payload = json_decode(json_encode($jwt), true);
|
||||
if (is_array($payload) && ($payload['scope'] ?? '') === 'wx') {
|
||||
return UtilsService::getInstance()->notAuth('请使用后台账号登录');
|
||||
}
|
||||
$data = $this->extractUserData($jwt);
|
||||
$userId = (int) ($data['id'] ?? 0);
|
||||
if ($userId <= 0) {
|
||||
return UtilsService::getInstance()->notAuth('Token 无效,请重新登录');
|
||||
}
|
||||
$user = RedisService::getInstance()->init(config('nl.redis.jwt'))->get($userId);
|
||||
if (empty($user)) {
|
||||
// Redis 会话丢了但签名有效:用 payload 顶住,避免刚登录就被踢
|
||||
return $data;
|
||||
}
|
||||
$decoded = json_decode($user, true);
|
||||
return is_array($decoded) ? $decoded : $data;
|
||||
} catch (\Throwable $e) {
|
||||
if ((int) $e->getCode() === 401) {
|
||||
throw $e;
|
||||
}
|
||||
return UtilsService::getInstance()->notAuth('【2】Token解析失败!请重新登录:'. $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从解码后的 JWT 取出用户数据
|
||||
*
|
||||
* 本系统签发的是 { data: { id, ... } };有的网关/旧 token 会把字段摊到顶层,
|
||||
* 或只留 sub。这里都认,避免再出现 Undefined property::$data。
|
||||
*/
|
||||
public function extractUserData(?object $jwt): array
|
||||
{
|
||||
if (!is_object($jwt)) {
|
||||
return [];
|
||||
}
|
||||
$payload = json_decode(json_encode($jwt), true);
|
||||
if (!is_array($payload)) {
|
||||
return [];
|
||||
}
|
||||
$data = $payload['data'] ?? null;
|
||||
if (is_array($data) && $data !== []) {
|
||||
return $data;
|
||||
}
|
||||
if (is_object($data)) {
|
||||
return (array) $data;
|
||||
}
|
||||
$id = $payload['id'] ?? $payload['sub'] ?? 0;
|
||||
if ((int) $id > 0) {
|
||||
return array_merge($payload, ['id' => (int) $id]);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 续签 JWT Token
|
||||
* @return string|null 新的 JWT 字符串或者 null 如果原 token 已过期或无效
|
||||
@@ -116,11 +170,12 @@ class JWTService
|
||||
public function refreshToken(): ?string
|
||||
{
|
||||
$decoded = $this->parseToken();
|
||||
if ($decoded === null || !property_exists($decoded, 'data')) {
|
||||
$data = $this->extractUserData($decoded);
|
||||
if (($data['id'] ?? 0) <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->generateToken((array)$decoded->data);
|
||||
return $this->generateToken($data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user