harry/think-jwt

JSON Web Token (JWT) for ThinkPHP plugin

Maintainers

Package info

github.com/harryYKH/think-jwt

pkg:composer/harry/think-jwt

Transparency log

Statistics

Installs: 5

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

0.1.0 2026-08-27 00:28 UTC

This package is auto-updated.

Last update: 2026-08-27 00:30:27 UTC


README

Latest Stable Version Total Downloads License PHP Version Require

基于 PHP 8.4 重构的 ThinkPHP JWT 认证组件,采用现代 PHP 特性与领域驱动设计。

架构概览

src/
├── JWT.php                      # 门面入口
├── RedisHandler                 # Redis 兼容层
├── Enum/
│   └── TokenType.php            # 令牌类型枚举
├── DTO/
│   ├── JWTConfig.php            # 配置只读对象
│   └── TokenPayload.php         # 载荷数据对象
├── Contract/
│   └── TokenStorageInterface.php # 存储接口
├── Storage/
│   └── RedisTokenStorage.php    # Redis 存储实现
├── Service/
│   ├── TokenFactory.php         # 令牌工厂
│   └── TokenValidator.php       # 令牌验证器
├── Exception/                   # 异常体系
└── config.php                   # 默认配置

设计模式

模式 应用
门面模式 JWT 类提供统一静态入口
工厂模式 TokenFactory 负责创建令牌对
策略模式 TokenStorageInterface 解耦存储实现
DTO 模式 JWTConfig / TokenPayload 只读数据对象
枚举 TokenType 替代类常量

安装

composer require harry/think-jwt

配置

发布配置文件到 config/jwt.php

return [
    'algorithms' => 'HS256',
    'access_secret_key' => 'your-access-secret',
    'refresh_secret_key' => 'your-refresh-secret',
    'access_exp' => 7200,       // 2 小时
    'refresh_exp' => 604800,    // 7 天
    'iss' => 'your-app.com',
    'single_device' => false,
    'refresh_is_store' => false,
    'user_model' => fn(int $uid) => User::find($uid)?->toArray(),
];

使用

生成令牌

use harry\JWT;
use harry\Enum\TokenType;

$user = ['id' => 2026, 'name' => 'Harry', 'email' => 'harry@163.com'];
$token = JWT::generateToken($user);

// 返回
// [
//     'token_type' => 'Bearer',
//     'expires_in' => 7200,
//     'access_token' => 'eyJ...',
//     'refresh_token' => 'eyJ...',
// ]

验证令牌

use harry\JWT;
use harry\Enum\TokenType;

/** @var \harry\DTO\TokenPayload $payload */
$payload = JWT::verify(TokenType::Access);

echo $payload->userId();              // 用户ID
echo $payload->claim('name');         // 自定义字段
echo $payload->expiresAt;             // 过期时间戳

从请求头验证

// 自动从 Authorization 头解析 Bearer 令牌
$payload = JWT::verify();

刷新令牌

$newToken = JWT::refreshToken();
// ['access_token' => 'eyJ...']

获取当前用户信息

$uid = JWT::getCurrentId();
$role = JWT::getCurrentRoleCode();
$allClaims = JWT::getExtend();
$email = JWT::getExtendVal('email');
$user = JWT::getUser();  // 通过 user_model 回调获取

删除刷新令牌

JWT::deleteRefreshToken('2026');

API 速查

方法 说明
JWT::generateToken(array $claims) 生成令牌对
JWT::verify(?TokenType $type, ?string $token) 验证令牌,返回 TokenPayload
JWT::refreshToken() 刷新 Access 令牌
JWT::getCurrentId() 获取当前用户ID
JWT::getCurrentRoleCode() 获取角色code
JWT::getCurrentRoleId() 获取角色ID
JWT::getUser() 获取用户信息(通过模型回调)
JWT::getExtend() 获取所有扩展字段
JWT::getExtendVal(string $key) 获取指定扩展字段
JWT::getTokenExp(?TokenType $type) 获取剩余有效期(秒)
JWT::deleteRefreshToken(string $userId) 删除刷新令牌

高级用法

自定义配置注入

use harry\JWT;
use harry\DTO\JWTConfig;

$config = new JWTConfig(
    algorithms: 'RS256',
    accessPrivateKey: file_get_contents('/path/to/private.pem'),
    accessPublicKey: file_get_contents('/path/to/public.pem'),
    accessTtl: 3600,
);

JWT::configure($config);

自定义存储实现

use harry\Contract\TokenStorageInterface;

class DatabaseTokenStorage implements TokenStorageInterface
{
    public function store(string $key, string $token, int $ttl): bool { /* ... */ }
    public function retrieve(string $key): ?string { /* ... */ }
    public function delete(string $key): bool { /* ... */ }
    public function exists(string $key): bool { /* ... */ }
}

直接使用服务层

use harry\Service\TokenFactory;
use harry\Service\TokenValidator;
use harry\Storage\RedisTokenStorage;
use harry\DTO\JWTConfig;

$config = JWTConfig::fromArray(config('jwt'));
$storage = new RedisTokenStorage();

$factory = new TokenFactory($config, $storage);
$tokens = $factory->pair(['id' => '2026', 'role' => 'admin']);

$validator = new TokenValidator($config, $storage);
$payload = $validator->verify($tokens['access_token'], TokenType::Access);

签名算法

算法 类型 说明
HS256 / HS384 / HS512 对称 同一密钥签名验证
RS256 / RS384 / RS512 非对称 RSA 私钥签名,公钥验证
ES256 / ES384 / ES512 非对称 ECDSA 签名
Ed25519 非对称 EdDSA 签名(需 sodium 扩展)

生成 RSA 密钥对

ssh-keygen -t rsa -b 4096 -E SHA256 -m PEM -P "" -f rs256.key
openssl rsa -in rs256.key -pubout -outform PEM -out rs256.key.pub

异常体系

RuntimeException
├── JWTTokenException              # 通用令牌异常
│   ├── JWTTokenExpiredException   # 令牌已过期
│   └── JWTRefreshTokenExpiredException  # 刷新令牌过期
│       └── JWTStoreRefreshTokenExpiredException  # 存储的刷新令牌过期
└── JWTConfigException             # 配置异常

安全性建议

  1. 密钥管理:生产环境使用 RS256 非对称算法,私钥妥善保管
  2. HTTPS 传输:始终通过 HTTPS 传输令牌
  3. 令牌过期:设置合理的过期时间,Access 令牌建议 ≤ 2 小时
  4. 刷新令牌存储:开启 refresh_is_store 实现令牌吊销
  5. 单设备登录:开启 single_device 防止多设备同时在线
  6. 时序安全:使用 hash_equals 比较令牌,防止计时攻击

要求

  • PHP >= 8.4
  • topthink/framework >= 8.1.4
  • firebase/php-jwt >= 7.1
  • ext-redis(可选,用于 Redis 存储)

License

MIT