JSON Web令牌(JWT)已成为Web开发中各方之间安全传输信息的流行方法。在本指南中,我们将探索在PHP中创建、验证和解码JWT令牌,而不依赖于外部库。我们将利用 hash_hmac
生成签名,利用 base64_encode/decode
进行编码和解码。
环境配置
在深入研究代码之前,请确保您的服务器上安装了PHP。此外,您可能希望使用Composer来管理依赖项。在这个例子中,我们将创建一个独立的类来处理JWT操作。
composer init
composer require guzzlehttp/guzzle
JWT 类
现在,让我们创建一个名为 Jwt
的类来封装JWT操作:
<?php
class Jwt
{
/**string */
private string $secretKey;
/**
* @param string $secretKey
* @author Tinywan(ShaoBo Wan)
*/
public function __construct(string $secretKey)
{
$this->secretKey = $secretKey;
}
/**
* @desc create token
* @param array $payload
* @return string
* @author Tinywan(ShaoBo Wan)
*/
public function createToken(array $payload): string
{
// Implementation for creating JWT
}
/**
* @desc validate token
* @param string $token
* @return bool
* @author Tinywan(ShaoBo Wan)
*/
public function validateToken(string $token): bool
{
// Implementation for validating JWT
}
/**
* @desc decode token
* @param string $token
* @return array
* @author Tinywan(ShaoBo Wan)
*/
public function decodeToken(string $token): array
{
// Implementation for decoding JWT
}
// Helper functions for base64 URL encoding/decoding
}
创建JWT
让我们实现用于生成JWT的 createToken
方法:
/**
* @desc create token
* @param array $payload
* @return string
* @author Tinywan(ShaoBo Wan)
*/
public function createToken(array $payload): string
{
$base64UrlHeader = $this->base64UrlEncode(json_encode([\\\"alg\\\" => \\\"HS256\\\", \\\"typ\\\" => \\\"JWT\\\"]));
$base64UrlPayload = $this->base64UrlEncode(json_encode($payload));
$base64UrlSignature = hash_hmac(\\\'sha256\\\', $base64UrlHeader . \\\'.\\\' . $base64UrlPayload, $this->secretKey, true);
$base64UrlSignature = $this->base64UrlEncode($base64UrlSignature);
return $base64UrlHeader . \\\'.\\\' . $base64UrlPayload . \\\'.\\\' . $base64UrlSignature;
}
/**
* @desc base64_encode 编码
* @param string $data
* @return string
* @author Tinywan(ShaoBo Wan)
*/
private function base64UrlEncode(string $data): string
{
$base64 = base64_encode($data);
$base64Url = strtr($base64, \\\'+/\\\', \\\'-_\\\');
return rtrim($base64Url, \\\'=\\\');
}
/**
* @desc base64_encode 解码
* @param string $data
* @return string
* @author Tinywan(ShaoBo Wan)
*/
private function base64UrlDecode(string $data): string
{
$base64 = strtr($data, \\\'-_\\\', \\\'+/\\\');
$base64Padded = str_pad($base64, strlen($base64) % 4, \\\'=\\\', STR_PAD_RIGHT);
return base64_decode($base64Padded);
}
验证JWT
现在,让我们实现用于验证JWT的 validateToken
方法:
/**
* @desc validate token
* @param string $token
* @return bool
* @author Tinywan(ShaoBo Wan)
*/
public function validateToken(string $token): bool
{
list($base64UrlHeader, $base64UrlPayload, $base64UrlSignature) = explode(\\\'.\\\', $token);
$signature = $this->base64UrlDecode($base64UrlSignature);
$expectedSignature = hash_hmac(\\\'sha256\\\', $base64UrlHeader . \\\'.\\\' . $base64UrlPayload, $this->secretKey, true);
return hash_equals($signature, $expectedSignature);
}
解码JWT
最后,让我们实现用于解码JWT的 decodeToken
方法:
/**
* @desc decode token
* @param string $token
* @return array
* @author Tinywan(ShaoBo Wan)
*/
public function decodeToken(string $token): array
{
list(, $base64UrlPayload, ) = explode(\\\'.\\\', $token);
$payload = $this->base64UrlDecode($base64UrlPayload);
return json_decode($payload, true);
}
验证
<?php
require \\\'vendor/autoload.php\\\';
// Your secret key (keep this secure)
$secretKey = \\\'Tinywan2024040000011\\\';
// Create an instance of Jwt
$jwt = new \\\\Tinywan\\\\Jwt($secretKey);
// Create a JWT
$payload = [
\\\"user_id\\\" => 2024,
\\\"username\\\" => \\\"Tinywan\\\",
\\\"exp\\\" => time() + 3600, // Token expiration time (1 hour)
];
$token = $jwt->createToken($payload);
echo \\\'JWT Token: \\\' . $token . PHP_EOL;
// Validate and decode the JWT
if ($jwt->validateToken($token)) {
echo \\\'JWT is valid.\\\' . PHP_EOL;
$decodedPayload = $jwt->decodeToken($token);
echo \\\"Decoded Payload: \\\" . json_encode($decodedPayload, JSON_PRETTY_PRINT).PHP_EOL;
var_dump(json_decode(json_encode($decodedPayload), true));
} else {
echo \\\'JWT is invalid.\\\' . PHP_EOL;
}
输出
JWT Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoyMDI0LCJ1c2VybmFtZSI6IlRpbnl3YW4iLCJleHAiOjE3MTI1ODcyNTN9.7agfeUJxj-iE0oevkf_lQwmYZOcCd7ORHWycDNv27_I
JWT is valid.
Decoded Payload: {
\\\"user_id\\\": 2024,
\\\"username\\\": \\\"Tinywan\\\",
\\\"exp\\\": 1712587253
}
array(3) {
[\\\"user_id\\\"]=>
int(2024)
[\\\"username\\\"]=>
string(7) \\\"Tinywan\\\"
[\\\"exp\\\"]=>
int(1712587253)
}
在本例中,我们创建了一个JWT,其有效负载包含用户ID、用户名和过期时间。然后我们使用我们的 Jwt类验证和解码JWT。
源码地址:https://github.com/Tinywan/jwt
原创文章,作者:网络技术联盟站,如若转载,请注明出处:https://www.sudun.com/ask/49902.html