<?php
namespace app\api\controller;
class Jwts
{
private static $secretKey = 'hlkkeko4u8tefk234%#$WETGREG{|'; // 加密使用的秘钥 尽可能复杂
private static $algo = 'HS256'; // 使用的算法
/**
* 生成JWT
*
* @param array $payload 数据负载
* @param int $expire 过期时间(秒),null表示不过期
* @return string
*/
public static function generateJWT($payload)
{
// 1. 生成header
$header = json_encode(['alg' => self::$algo, 'typ' => 'JWT']);
$base64Header = self::base64UrlEncode($header);
// 2. 生成payload
$payload['exp'] = time() + 1296000; //过期时间
$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, '-_', '+/'));
}
}
调用demo
public function login()
{
$user_data = [
'id' => 1,
];
$token = Jwts::generateJWT($user_data);
print_r($token);
}
//验证token
public function verify(){
$token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwiZXhwIjoxNzQ3ODExNDAyfQ.l1mRV-Xfs4mrctZDPhDnZGP8-Wa8iX2-kNA61OLp8rs';
if (!$token) {
$this->error('Token不能为空');
}
// 验证Token
$payload = Jwts::verifyJWT($token);
if (!$payload) {
$this->error('Token无效或已过期','',202);
}
以上两个步骤完成了JWT的封装 为了安全起见 可以在加密一层 对JWT进行加密
/**
* 使用AES-256-CBC算法进行字符串加解密
*
* @param string $string 要加密/解密的字符串
* @param string $key 加密密钥
* @param bool $encrypt 是否加密(true)或解密(false)
* @return string 处理后的字符串
* @throws Exception 当密钥长度不足或加密失败时抛出异常
*/
public function encryptDecryptString($string, $key, $encrypt = true) {
// 检查密钥长度,AES-256需要32字节密钥
if (strlen($key) < 32) {
// 如果密钥不足32字节,使用PKCS7填充方式补足
$key = str_pad($key, 32, "\0");
} elseif (strlen($key) > 32) {
// 如果密钥超过32字节,截取前32字节
$key = substr($key, 0, 32);
}
// 初始化向量(IV) - 加密时需要随机生成,解密时需要从密文中提取
$ivLength = openssl_cipher_iv_length('aes-256-cbc');
$iv = openssl_random_pseudo_bytes($ivLength);
try {
if ($encrypt) {
// 加密模式
$encrypted = openssl_encrypt($string, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
// 将IV和加密后的数据合并,IV前缀在解密时需要用到
// 通常会将IV和密文一起存储/传输
return base64_encode($iv . $encrypted);
} else {
// 解密模式
$data = base64_decode($string);
$iv = substr($data, 0, $ivLength);
$encrypted = substr($data, $ivLength);
return openssl_decrypt($encrypted, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
}
} catch (Exception $e) {
throw new Exception("加解密操作失败: " . $e->getMessage());
}
}
OK 这样应该是很安全了 如果有更好的意见欢迎提出
3043

被折叠的 条评论
为什么被折叠?



