1. JWT (JSON Web Token)
最流行的无状态Token方案
实现方式:
// 使用firebase/php-jwt库
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
class JWTToken {
private $secretKey = 'your-secret-key';
public function createToken($userId, $data = []) {
$payload = [
'user_id' => $userId,
'data' => $data,
'iat' => time(),
'exp' => time() + 3600 // 1小时过期
];
return JWT::encode($payload, $this->secretKey, 'HS256');
}
public function validateToken($token) {
try {
$decoded = JWT::decode($token, new Key($this->secretKey, 'HS256'));
return (array)$decoded;
} catch (\Exception $e) {
return false;
}
}
}
优点:
- 无状态,服务端无需存储
- 自包含,可携带用户信息
- 适合分布式系统
缺点:
- Token无法主动失效(需配合黑名单)
- 数据公开(可用加密JWE解决)
2. OAuth2 Access Token
标准的授权框架方案
实现方式:
// 使用league/oauth2-server库
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\Grant\PasswordGrant;
class OAuthToken {
private $server;
public function __construct() {
// 初始化客户端存储、scope存储、token存储等
$clientRepository = new ClientRepository();
$scopeRepository = new ScopeRepository();
$accessTokenRepository = new AccessTokenRepository();
$this->server = new AuthorizationServer(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
'path/to/private.key',
'path/to/public.key'
);
// 配置授权类型
$grant = new PasswordGrant(
new UserRepository(),
new RefreshTokenRepository()
);
$grant->setRefreshTokenTTL(new \DateInterval('P1M'));
$this->server->enableGrantType($grant, new \DateInterval('PT1H'));
}
public function issueToken($username, $password) {
$request = new ServerRequest('POST', '/token');
$request = $request->withParsedBody([
'grant_type' => 'password',
'username' => $username,
'password' => $password
]);
return $this->server->respondToAccessTokenRequest($request, new Response());
}
}
优点:
- 标准化协议
- 支持多种授权流程
- 良好的安全性和扩展性
缺点:
3. 数据库Session Token
传统的有状态Token方案
实现方式:
class DatabaseToken {
private $db;
private $table = 'user_tokens';
public function createToken($userId, $clientInfo = []) {
$token = bin2hex(random_bytes(32));
$expiresAt = date('Y-m-d H:i:s', time() + 3600);
$this->db->prepare("
INSERT INTO {$this->table}
(user_id, token, expires_at, client_info, created_at)
VALUES (?, ?, ?, ?, NOW())
")->execute([
$userId,
$token,
$expiresAt,
json_encode($clientInfo)
]);
return $token;
}
public function validateToken($token) {
$stmt = $this->db->prepare("
SELECT * FROM {$this->table}
WHERE token = ? AND expires_at > NOW() AND revoked = 0
");
$stmt->execute([$token]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
public function revokeToken($token) {
$this->db->prepare("
UPDATE {$this->table} SET revoked = 1 WHERE token = ?
")->execute([$token]);
}
}
优点:
- 可完全控制token生命周期
- 易于管理和撤销
- 可记录token使用日志
缺点:
4. 加密Token (自实现方案)
简单可控的自定义方案
实现方式:
class EncryptedToken {
private $key;
private $cipher = 'AES-256-GCM';
public function __construct($key) {
$this->key = $key;
}
public function createToken($data) {
$iv = random_bytes(openssl_cipher_iv_length($this->cipher));
$data['exp'] = time() + 3600;
$data['iat'] = time();
$plaintext = json_encode($data);
$ciphertext = openssl_encrypt(
$plaintext,
$this->cipher,
$this->key,
OPENSSL_RAW_DATA,
$iv,
$tag
);
// Base64编码便于传输
return base64_encode($iv . $tag . $ciphertext);
}
public function validateToken($token) {
$decoded = base64_decode($token);
$ivLength = openssl_cipher_iv_length($this->cipher);
$tagLength = 16; // GCM标签长度
$iv = substr($decoded, 0, $ivLength);
$tag = substr($decoded, $ivLength, $tagLength);
$ciphertext = substr($decoded, $ivLength + $tagLength);
$plaintext = openssl_decrypt(
$ciphertext,
$this->cipher,
$this->key,
OPENSSL_RAW_DATA,
$iv,
$tag
);
if ($plaintext === false) {
return false;
}
$data = json_decode($plaintext, true);
// 检查过期时间
if (isset($data['exp']) && $data['exp'] < time()) {
return false;
}
return $data;
}
}
优点:
缺点:
方案对比
| 特性 |
JWT |
OAuth2 |
数据库Token |
加密Token |
|---|
| 状态 |
无状态 |
有状态 |
有状态 |
无状态 |
| 安全性 |
高 |
很高 |
高 |
取决于实现 |
| 性能 |
高 |
中 |
低 |
高 |
| 扩展性 |
好 |
很好 |
一般 |
一般 |
| 实现复杂度 |
低 |
高 |
中 |
中 |
| 适用场景 |
API、微服务 |
第三方授权、企业应用 |
Web应用、需精确控制 |
简单API、内部系统 |
选择建议
纯API项目 → 推荐
JWT
需要第三方授权 → 推荐
OAuth2
传统Web应用 → 推荐
数据库Token 或 Session
简单内部系统 → 推荐
加密Token
最佳实践补充
// 无论选择哪种方案都应考虑:
class TokenBestPractices {
// 1. 使用HTTPS传输
// 2. 设置合适的过期时间
// 3. 实现Refresh Token机制
// 4. 记录Token使用日志
// 5. 提供Token撤销功能
// 6. 防范CSRF攻击
// 7. 定期更换密钥
}
根据具体需求选择合适的Token方案,并在项目中保持一致性。