分享一个TP框架的JWT的简单方法 很简单

<?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 这样应该是很安全了 如果有更好的意见欢迎提出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值