91 lines
2.2 KiB
PHP
91 lines
2.2 KiB
PHP
|
|
<?php
|
|||
|
|
|
|||
|
|
namespace App\Helpers;
|
|||
|
|
|
|||
|
|
use DateTimeImmutable;
|
|||
|
|
|
|||
|
|
class TokenHelper
|
|||
|
|
{
|
|||
|
|
private static $secret = 'ufutx_love_util';
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 生成 token
|
|||
|
|
* @param int $userId 用户ID
|
|||
|
|
* @param int $expiresIn 过期时间(分钟)
|
|||
|
|
* @return string
|
|||
|
|
*/
|
|||
|
|
public static function generate($userId, $expiresIn = 60)
|
|||
|
|
{
|
|||
|
|
$now = time();
|
|||
|
|
$expires = $now + ($expiresIn * 60);
|
|||
|
|
|
|||
|
|
$payload = [
|
|||
|
|
'user_id' => $userId,
|
|||
|
|
'iat' => $now,
|
|||
|
|
'exp' => $expires
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
// 使用更简单的方式:base64 编码(避免版本兼容问题)
|
|||
|
|
$encoded = base64_encode(json_encode($payload));
|
|||
|
|
|
|||
|
|
// 添加签名
|
|||
|
|
$signature = hash_hmac('sha256', $encoded, self::$secret);
|
|||
|
|
|
|||
|
|
return $encoded . '.' . $signature;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 验证 token
|
|||
|
|
* @return array|false
|
|||
|
|
*/
|
|||
|
|
public static function verify($tokenString)
|
|||
|
|
{
|
|||
|
|
try {
|
|||
|
|
$parts = explode('.', $tokenString);
|
|||
|
|
if (count($parts) != 2) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
list($payloadEncoded, $signature) = $parts;
|
|||
|
|
|
|||
|
|
// 验证签名
|
|||
|
|
$expectedSignature = hash_hmac('sha256', $payloadEncoded, self::$secret);
|
|||
|
|
if (!hash_equals($expectedSignature, $signature)) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 解码 payload
|
|||
|
|
$payload = json_decode(base64_decode($payloadEncoded), true);
|
|||
|
|
if (!$payload) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查是否过期
|
|||
|
|
$now = time();
|
|||
|
|
if (isset($payload['exp']) && $payload['exp'] < $now) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return [
|
|||
|
|
'user_id' => $payload['user_id'],
|
|||
|
|
'expires_at' => $payload['exp']
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
} catch (\Exception $e) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 刷新 token
|
|||
|
|
*/
|
|||
|
|
public static function refresh($oldToken, $expiresIn = 60)
|
|||
|
|
{
|
|||
|
|
$payload = self::verify($oldToken);
|
|||
|
|
if (!$payload) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return self::generate($payload['user_id'], $expiresIn);
|
|||
|
|
}
|
|||
|
|
}
|