引入lcobucci/jwt写了token

127 阅读1分钟
<?php

// App/Services/Service/JwtService.php
namespace App\Services\Service;

use App\Services\Implement\JwtInterface;
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\Token\Plain;
use Lcobucci\JWT\Validation\Constraint\SignedWith;
use Lcobucci\JWT\Validation\Constraint\ValidAt;
use Lcobucci\Clock\SystemClock;
use Redis;

class JwtService implements JwtInterface {
    public Configuration $jwtConfig;
    private int $jwtExp;
    private Redis $redis;

    public function __construct() {
        $config = \PhalApi\DI()->config->get('app.jwt');
        $this->jwtExp = $config['exp'];

        $this->jwtConfig = Configuration::forSymmetricSigner(
            new Sha256(),
            InMemory::plainText($config['secret'])
        );

        $this->redis = \PhalApi\DI()->redis->getRedis();
    }

    public function generateToken($user): string {
        $now = new \DateTimeImmutable();
        $exp = $now->modify('+' . $this->jwtExp . ' seconds');

        $token = $this->jwtConfig->builder()
            ->issuedBy('your_domain.com')
            ->permittedFor('your_domain.com')
            ->issuedAt($now)
            ->expiresAt($exp)
            ->withClaim('id', $user['id'])
            ->withClaim('username', $user['username'])
            ->withClaim('role', $user['role_id'])
            ->getToken($this->jwtConfig->signer(), $this->jwtConfig->signingKey());

        return $token->toString();
    }

    public function validateToken($token): bool {
        if ($this->isTokenBlacklisted($token)) {
            return false;
        }

        try {
            $token = $this->jwtConfig->parser()->parse($token);
            assert($token instanceof Plain);

            $constraints = [
                new SignedWith($this->jwtConfig->signer(), $this->jwtConfig->verificationKey()),
                new ValidAt(SystemClock::fromUTC())
            ];

            $this->jwtConfig->validator()->assert($token, ...$constraints);

            return true;
        } catch (\Exception $e) {
            return false;
        }
    }

    public function getUserIdFromToken($token): ?int {
        try {
            $token = $this->jwtConfig->parser()->parse($token);
            assert($token instanceof Plain);

            return $token->claims()->get('id');
        } catch (\Exception $e) {
            return null;
        }
    }

    public function addTokenToBlacklist(string $token, int $exp) {
        $this->redis->setex($token, $exp, 'blacklisted');
    }

    public function isTokenBlacklisted(string $token): bool {
        return $this->redis->exists($token) === 1;
    }
}