62 lines
1.6 KiB
PHP
62 lines
1.6 KiB
PHP
<?php
|
|
|
|
namespace app\service;
|
|
|
|
class JwtService
|
|
{
|
|
public static function generateToken(array $payload): string
|
|
{
|
|
$secret = config('jwt.secret');
|
|
$expire = config('jwt.expire');
|
|
|
|
$header = self::base64UrlEncode(json_encode(['typ' => 'JWT', 'alg' => 'HS256']));
|
|
$payload['exp'] = time() + $expire;
|
|
$payload['iat'] = time();
|
|
$body = self::base64UrlEncode(json_encode($payload));
|
|
$signature = self::base64UrlEncode(hash_hmac('sha256', "{$header}.{$body}", $secret, true));
|
|
|
|
return "{$header}.{$body}.{$signature}";
|
|
}
|
|
|
|
public static function verifyToken(?string $token): ?array
|
|
{
|
|
if (!$token) {
|
|
return null;
|
|
}
|
|
|
|
if (str_starts_with($token, 'Bearer ')) {
|
|
$token = substr($token, 7);
|
|
}
|
|
|
|
$parts = explode('.', $token);
|
|
if (count($parts) !== 3) {
|
|
return null;
|
|
}
|
|
|
|
[$header, $body, $signature] = $parts;
|
|
$secret = config('jwt.secret');
|
|
$expected = self::base64UrlEncode(hash_hmac('sha256', "{$header}.{$body}", $secret, true));
|
|
|
|
if (!hash_equals($expected, $signature)) {
|
|
return null;
|
|
}
|
|
|
|
$payload = json_decode(self::base64UrlDecode($body), true);
|
|
if (!$payload || ($payload['exp'] ?? 0) < time()) {
|
|
return null;
|
|
}
|
|
|
|
return $payload;
|
|
}
|
|
|
|
private static function base64UrlEncode(string $data): string
|
|
{
|
|
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
|
|
}
|
|
|
|
private static function base64UrlDecode(string $data): string
|
|
{
|
|
return base64_decode(strtr($data, '-_', '+/'));
|
|
}
|
|
}
|