Files
MBTI_wang/api/app/common/service/JwtService.php
2026-03-17 12:39:38 +08:00

133 lines
3.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\common\service;
use think\facade\Cache;
/**
* JWT Token 服务类
*/
class JwtService
{
/**
* 生成Token
* @param array $payload 载荷数据
* @return string
*/
public static function generateToken(array $payload): string
{
$secret = config('jwt.secret', 'mbti_jwt_secret_key_2024');
$expire = config('jwt.expire', 86400 * 7); // 默认7天
// 添加过期时间
$payload['exp'] = time() + $expire;
$payload['iat'] = time();
// 生成Token简单方案base64编码 + 签名)
$header = base64_encode(json_encode(['typ' => 'JWT', 'alg' => 'HS256']));
$payloadStr = base64_encode(json_encode($payload));
$signature = hash_hmac('sha256', $header . '.' . $payloadStr, $secret);
$token = $header . '.' . $payloadStr . '.' . $signature;
// 将Token存储到缓存用于刷新和注销带 source 区分小程序用户与管理员
$userId = $payload['userId'] ?? $payload['user_id'] ?? null;
if ($userId !== null) {
$key = self::tokenCacheKey($userId, $payload['source'] ?? null);
Cache::set($key, $token, $expire);
}
return $token;
}
/**
* 验证Token
* @param string $token
* @return array|false 返回载荷数据或false
*/
public static function verifyToken(string $token)
{
$parts = explode('.', $token);
if (count($parts) !== 3) {
return false;
}
[$header, $payloadStr, $signature] = $parts;
// 验证签名
$secret = config('jwt.secret', 'mbti_jwt_secret_key_2024');
$expectedSignature = hash_hmac('sha256', $header . '.' . $payloadStr, $secret);
if ($signature !== $expectedSignature) {
return false;
}
// 解析载荷
$payload = json_decode(base64_decode($payloadStr), true);
if (!$payload) {
return false;
}
// 检查过期时间
if (isset($payload['exp']) && $payload['exp'] < time()) {
return false;
}
return $payload;
}
/**
* 刷新Token
* @param string $token
* @return string|false 返回新Token或false
*/
public static function refreshToken(string $token)
{
$payload = self::verifyToken($token);
if (!$payload) {
return false;
}
// 移除过期时间字段,重新生成
unset($payload['exp'], $payload['iat']);
return self::generateToken($payload);
}
/**
* Token 缓存键(区分来源,避免与管理员同 id 冲突)
*/
public static function tokenCacheKey($userId, ?string $source = null): string
{
$prefix = $source ? 'jwt_token_' . $source . '_' : 'jwt_token_';
return $prefix . $userId;
}
/**
* 删除Token注销
* @param int $userId
* @param string|null $source 来源,如 wechat不传则按管理员 token 键删除
* @return bool
*/
public static function deleteToken(int $userId, ?string $source = null): bool
{
return Cache::delete(self::tokenCacheKey($userId, $source));
}
/**
* 从请求头获取Token
* @param \think\Request $request
* @return string|null
*/
public static function getTokenFromRequest($request): ?string
{
$authorization = $request->header('Authorization', '');
if ($authorization && preg_match('/Bearer\s+(.*)$/i', $authorization, $matches)) {
return $matches[1];
}
return null;
}
}