在 PHP 中,JSON Web Token (JWT) 是一种开放标准 (RFC 7519) 用于在各方之间作为 JSON 对象安全地传输信息。JWT 通常用于身份验证系统,如 OAuth2 或基于令牌的身份验证。
以下是一个基本的 PHP 实现 JWT 生成和验证的代码示例。
JWT 的组成部分
JWT 包含三个部分:
- Header(头部):说明算法和令牌类型。
- Payload(有效载荷):包含声明(如用户数据、过期时间等)。
- Signature(签名):用于验证令牌是否被篡改。
JWT 格式如下:header.payload.signature
基本步骤
- 编码:使用 Base64 编码 Header 和 Payload。
- 签名:使用 Header 中定义的算法对编码后的 Header 和 Payload 进行签名。
- 验证:解析 JWT 时,通过检查签名是否有效来验证令牌。
代码实现
<?php
class JWT
{
private static $secretKey = 'your_secret_key'; // 加密使用的秘钥
private static $algo = 'HS256'; // 使用的算法
/**
* 生成JWT
*
* @param array $payload 数据负载
* @return string
*/
public static function generateJWT($payload)
{
// 1. 生成header
$header = json_encode(['alg' => self::$algo, 'typ' => 'JWT']);
$base64Header = self::base64UrlEncode($header);
// 2. 生成payload
$base64Payload = self::base64UrlEncode(json_encode($payload));
// 3. 生成signature
$signature = hash_hmac('sha256', "$base64Header.$base64Payload", self::$secretKey, true);
$base64Signature = self::base64UrlEncode($signature);
// 4. 组合JWT
$jwt = "$base64Header.$base64Payload.$base64Signature";
return $jwt;
}
/**
* 验证JWT
*
* @param string $token JWT令牌
* @return array|bool 如果验证成功返回payload,否则返回false
*/
public static function verifyJWT($token)
{
// 1. 拆分JWT
$parts = explode('.', $token);
if (count($parts) !== 3) {
return false;
}
list($base64Header, $base64Payload, $base64Signature) = $parts;
// 2. 解码Header和Payload
$header = json_decode(self::base64UrlDecode($base64Header), true);
$payload = json_decode(self::base64UrlDecode($base64Payload), true);
$signature = self::base64UrlDecode($base64Signature);
// 3. 验证签名
$expectedSignature = hash_hmac('sha256', "$base64Header.$base64Payload", self::$secretKey, true);
if (!hash_equals($signature, $expectedSignature)) {
return false;
}
// 4. 验证过期时间
if (isset($payload['exp']) && $payload['exp'] < time()) {
return false;
}
return $payload;
}
/**
* Base64URL编码
*
* @param string $data
* @return string
*/
private static function base64UrlEncode($data)
{
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
/**
* Base64URL解码
*
* @param string $data
* @return string
*/
private static function base64UrlDecode($data)
{
return base64_decode(strtr($data, '-_', '+/'));
}
}
说明:
-
生成 JWT:
- 使用
generateJWT($payload)
方法生成 JWT。 header
包含签名算法信息(这里使用HS256
),payload
包含用户信息或其他声明。- 用
hash_hmac('sha256')
方法签名生成的 JWT。
- 使用
-
验证 JWT:
- 使用
verifyJWT($token)
方法验证 JWT。 - 验证签名是否正确,以及
payload
中是否设置了过期时间(可选)。
- 使用
-
Base64 编码/解码:
- 使用
base64UrlEncode()
和base64UrlDecode()
实现 URL 安全的 Base64 编码。
- 使用
测试代码
// 测试JWT生成
$payload = [
'user_id' => 123,
'username' => 'john_doe',
'exp' => time() + 3600 // 过期时间1小时
];
$jwt = JWT::generateJWT($payload);
echo "Generated JWT: " . $jwt . PHP_EOL;
// 测试JWT验证
$decodedPayload = JWT::verifyJWT($jwt);
if ($decodedPayload) {
echo "JWT is valid! Payload: " . print_r($decodedPayload, true) . PHP_EOL;
} else {
echo "Invalid JWT!" . PHP_EOL;
}
JWT 生成结果示例
Generated JWT: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJ1c2VyX2lkIjogMTIzLCAidXNlcm5hbWUiOiAiam9obl9kb2UiLCAiZXhwIjogMTYxNjg1MjIwMn0.J0wLkhlUkTftKzVzR7Y9pVwSBU-WESCTwks2FyUwDUU
JWT is valid! Payload: Array
(
[user_id] => 123
[username] => john_doe
[exp] => 1616852202
)
说明:
- 过期时间
exp
:你可以在payload
中加入exp
,它代表 JWT 过期的时间戳,通常用来限制令牌的有效期。 - 签名算法:这里使用的是
HS256
(HMAC-SHA256),你可以根据需求换成其他的对称或非对称签名算法。
应用场景
- 用户认证:基于 JWT 的用户登录、身份验证机制。
- API 授权:通过 JWT 传递身份验证信息,允许或拒绝 API 请求。
- 微服务间通信:在分布式系统中,JWT 可以用于服务之间的身份验证和授权。