如何使用 PHP 创建 JSON Web Token

2025-06-10

如何使用 PHP 创建 JSON Web Token

过去一年,我断断续续地开发了一个名为ReallySimpleJWT的 PHP JSON Web Token 库,本周发布了1.0.0 版本。代码可以通过GitHubPackagist访问。

对于从未使用过 JSON Web Tokens 的用户来说,它是一个基于 Token 的 URL 友好身份验证系统。它允许你通过编码的 JSON 负载轻松传输信息。

JSON Web Tokens 的核心优势有两个:您不需要使用会话或 cookie 来维护状态之间的身份验证;并且您不必不断地调用数据库来获取用户信息,因为这些信息可以存储在令牌有效负载中。

每个标记分为三个部分,每个部分由点分隔。

  • 标头:包含有关令牌类型(通常是 JWT)和使用的哈希算法(例如 HMAC SHA256 或 RSA)的信息。
  • 有效载荷:这包含您希望传输的有关用户的任何信息,例如用户标识符。
  • 签名:这可以保护令牌,它是编码的标头和有效负载的哈希值以及秘密。
// Token structure
header.payload.signature

// A real world token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

JWT 安全性是通过签名实现的,签名是通过对编码的标头和有效负载进行散列创建的,并使用只有作者知道的秘密来保护它。

当从用户收到令牌时,作者将能够通过使用已知密钥对接收到的标头和有效负载进行重新哈希处理,并检查其是否与接收到的签名匹配,从而验证签名。如果有人篡改标头或有效负载,则签名将不匹配,身份验证将失败。

如果您希望快速开始使用 JWT,ReallySimpleJWT库提供了一个易于使用的界面来生成和验证 JSON Web 令牌。

use ReallySimpleJWT\Token;

// Generate a token
$token = Token::getToken('userIdentifier', 'secret', 'tokenExpiryDateTimeString', 'issuerIdentifier');

// Validate the token
$result = Token::validate($token, 'secret');

如果您需要在简单的 API 上快速实现用户身份验证,它是完美的选择。如果您想阅读文档,该库还提供更多高级用法和功能。

如何在 PHP 中构建 JSON Web Token

如果您想构建自己的 JWT 生成器,或者只是想稍微了解一下,以下指南将对您有所帮助。虽然以下示例使用 PHP 编写,但其概念适用于任何语言,因此所有开发人员都应该觉得它们很有用。完整脚本位于本指南的底部。

创建标头和有效载荷

首先,我们需要创建标头和有效负载的 JSON 字符串。我们将基于两个简单的数组来实现,每个数组都声明了关于令牌的多个声明。您可以在相关的RFC中阅读更多关于声明的内容。对于标头,我们定义了类型typ和算法alg声明,它们是 RFC 标准声明;对于有效负载,我们将创建自己的声明user_id

// Create token header as a JSON string
$header = json_encode(['typ' => 'JWT', 'alg' => 'HS256']);

// Create token payload as a JSON string
$payload = json_encode(['user_id' => 123]);

创建 Base64Url 标头和有效负载字符串

$header接下来,我们将和JSON 字符串编码$payload为 Base64Url 字符串。这与标准的 Base64 字符串略有不同,而且 PHP 目前还没有内置的 Base64Url 方法。因此,我们需要进行一些字符串替换操作,+分别将-/_替换=''。这样,Base64 字符串就可以在 URL 中传递,而无需进行任何 URL 编码。

// Encode Header to Base64Url String
$base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));

// Encode Payload to Base64Url String
$base64UrlPayload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($payload));

创建签名

要创建签名,我们需要使用hash_hmac()PHP 中提供的方法并使用 sha256 算法。我们传入一个由 Base64Url 编码的 header 和 payload 组成的字符串$base64UrlHeader . "." . $base64UrlPayload。需要注意的是,.两个字符串之间必须包含一个点。我们添加一个 secret,最好是一个长度超过 12 个字符的强加密 secret。ReallySimpleJWT 库强制执行了这一原则,但对于我们的示例,我们无需担心。最后,我们强制该hash_hmac()方法以二进制数据形式返回输出。

// Create Signature Hash
$signature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, 'abC123!', true);

Base64Url 编码签名

一旦我们创建了签名,我们只需对其进行 Base64Url 编码,就像对标头和有效负载所做的那样。

// Encode Signature to Base64Url String
$base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));

创建 JSON Web 令牌

最后,我们通过连接 header $base64UrlHeader、payload$base64UrlPayload和 signature来创建 JWT。JWT$base64UrlSignature的每个部分都用点分隔。

// Create JWT
$jwt = $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature;

// Output
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxMjN9.NYlecdiqVuRg0XkWvjFvpLvglmfR1ZT7f8HeDDEoSx8

就是这样,非常简单。您可以在JWT.io 网站上测试此代码生成的 JWT 。完整代码如下,建议您阅读JWT 网站上的相关文档以及RFC

当然,如果您愿意,也可以使用ReallySimpleJWT 库。我会在接下来的一两周内发布一篇关于验证 JWT 的文章。如果您有任何想法或发现任何错误,请在 Twitter 上给我留言:@RobDWaller

剧本

// Create token header as a JSON string
$header = json_encode(['typ' => 'JWT', 'alg' => 'HS256']);

// Create token payload as a JSON string
$payload = json_encode(['user_id' => 123]);

// Encode Header to Base64Url String
$base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));

// Encode Payload to Base64Url String
$base64UrlPayload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($payload));

// Create Signature Hash
$signature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, 'abC123!', true);

// Encode Signature to Base64Url String
$base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));

// Create JWT
$jwt = $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature;

echo $jwt;
鏂囩珷鏉ユ簮锛�https://dev.to/robdwaller/how-to-create-a-json-web-token-using-php-3gml
PREV
技术项目失败的原因:管理、规划、流程
NEXT
PHP 类型声明如何工作