PHP中的JWT令牌:身份验证与授权完全指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

PHP中的JWT令牌:实现完全指南



JWT(JSON Web Token)是一种基于JSON格式的开放标准(RFC 7519),用于创建访问令牌。在PHP中,JWT被广泛用于在REST API、单页应用程序(SPA)和微服务中实现无状态身份验证(stateless authentication)。



在本文中,我们将详细讲解如何在PHP中使用JWT令牌:从库的安装到令牌的创建、验证与刷新。



什么是JWT,为什么需要它?



JWT由三部分组成,各部分之间用点号分隔:



  • Header(头部) — 包含令牌类型(JWT)和签名算法(例如HS256或RS256)。
  • Payload(有效载荷) — 包含声明(claims):用户标识符、角色、签发时间(iat)、过期时间(exp)以及其他数据。
  • Signature(签名) — 通过对头部和有效载荷进行哈希处理并使用密钥生成。


JWT的主要优势:

  • 无需在服务器上存储会话(无状态)。
  • 可以包含任意数据(例如用户角色)。
  • 适用于不同域名和移动应用程序。
  • 无需访问数据库即可轻松验证。


安装firebase/php-jwt库



为了在PHP中使用JWT,我们将使用流行的库firebase/php-jwt。通过Composer进行安装:



composer require firebase/php-jwt


安装后,项目中会出现Composer自动加载,需要引入它:



require_once 'vendor/autoload.php';

use Firebase\\JWT\\JWT;use Firebase\\JWT\\Key;


创建JWT令牌



要创建令牌,需要定义密钥($secretKey)并构建有效载荷。示例:



use Firebase\\JWT\\JWT;

$secretKey = 'your-256-bit-secret-key-here';$issuedAt = time();$expirationTime = $issuedAt + 3600; // 令牌有效期为1小时

$payload = [ 'iss' => 'pythonlib.ru', // 签发者 'iat' => $issuedAt, // 签发时间 'exp' => $expirationTime, // 过期时间 'sub' => 123, // 用户标识符 'role' => 'admin' // 自定义数据];

$jwt = JWT::encode($payload, $secretKey, 'HS256');echo $jwt;


结果将得到一个类似这样的字符串:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJweXRob25saWIucnUiLCJpYXQiOjE3Mjg0MDAwMDAsImV4cCI6MTcyODQwMzYwMCwic3ViIjoxMjMsInJvbGUiOiJhZG1pbiJ9.signature



验证和解码JWT



当从客户端收到令牌时(例如,从Authorization: Bearer <token>头部),需要对其进行验证:



use Firebase\\JWT\\JWT;use Firebase\\JWT\\Key;

$secretKey = 'your-256-bit-secret-key-here';$jwt = $_SERVER['HTTP_AUTHORIZATION'] ?? '';

try { $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256')); $userId = $decoded->sub; $role = $decoded->role; echo "用户 #{$userId} 角色为 {$role} 已授权。";} catch (\\Exception $e) { http_response_code(401); echo "错误: " . $e->getMessage();}


重要提示:该库会自动检查令牌的过期时间(exp)和签发时间(iat)。如果令牌已过期或无效,将抛出异常。



刷新JWT(Refresh Token)



为了提高安全性,JWT通常设置为短生命周期(15–60分钟)。对于长时间会话,可以使用Refresh Token——这是一个单独的令牌,存储在数据库中,允许在不重新输入用户名/密码的情况下获取新的Access Token。



刷新实现的示例:



function refreshAccessToken(string $ref                    

推荐