在 PHP 中,JWT(JSON Web Token) 是一种常用的用于身份验证和信息交换的令牌格式。JWT 通常包含三部分:头部、有效载荷和签名。通过签名验证,可以确保令牌的完整性和有效性。PHP 中处理 JWT 令牌的完整流程包括生成令牌、解析令牌和验证令牌。
目录
- 什么是 JWT(JSON Web Token)
- JWT 的结构
- 2.1 头部(Header)
- 2.2 有效载荷(Payload)
- 2.3 签名(Signature)
- PHP 中处理 JWT 的常见库
- PHP 生成 JWT 令牌
- PHP 解析和验证 JWT 令牌
- JWT 的使用场景
- 总结
1. 什么是 JWT(JSON Web Token)
JWT 是一种基于 JSON 的开放标准(RFC 7519),用于在网络应用环境间以可验证的方式安全地传输声明。JWT 通常用于实现 无状态的身份验证,并且广泛应用于 Web 应用程序和移动应用程序中。
JWT 的一个典型应用场景是通过 API 提供身份验证,尤其是在分布式系统中,服务器不需要存储状态信息,只需要验证 JWT 的合法性即可。
2. JWT 的结构
JWT 由三部分组成:
- 头部(Header):指定令牌的类型(通常是 JWT)以及所使用的签名算法(如 HMAC SHA256 或 RSA)。
- 有效载荷(Payload):包含声明(Claims)。声明是关于实体(通常是用户)和额外数据的信息。JWT 中有三种类型的声明:
- 注册声明(Registered Claims):如
iss
(发行者)、exp
(过期时间)等。 - 公共声明(Public Claims):可以自定义的声明。
- 私有声明(Private Claims):由双方自定义的声明,通常用于交换特定数据。
- 注册声明(Registered Claims):如
- 签名(Signature):用于验证令牌的完整性,确保令牌未被篡改。签名由头部、有效载荷和一个密钥(如 HMAC SHA256)共同生成。
JWT 令牌的格式如下:
header.payload.signature
2.1 头部(Header)
头部通常由两部分组成:
- typ:JWT(类型)。
- alg:签名算法,常见的有
HS256
、RS256
等。
例如:
{
"alg": "HS256",
"typ": "JWT"
}
2.2 有效载荷(Payload)
有效载荷包含声明,通常是用户的身份信息或其他自定义信息。示例如下:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
其中:
- sub:主题(subject),通常是用户的 ID。
- name:用户的名字。
- iat:签发时间(Issued At),表示令牌的创建时间。
2.3 签名(Signature)
签名部分是通过对头部和有效载荷进行编码后使用密钥生成的。生成签名的方式如下:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
3. PHP 中处理 JWT 的常见库
PHP 中有多个库可以处理 JWT 令牌,最常见的两个库是:
- Firebase JWT PHP(推荐):
- GitHub:https://github.com/firebase/php-jwt
- 安装:通过 Composer 安装
composer require firebase/php-jwt
- LCobucci JWT:
这里我们主要使用 Firebase JWT PHP 库进行演示。
4. PHP 生成 JWT 令牌
使用 Firebase JWT 库,可以非常简便地生成 JWT 令牌。下面是如何生成 JWT 令牌的完整过程。
安装 Firebase JWT 库
通过 Composer 安装:
composer require firebase/php-jwt
生成 JWT 令牌的示例代码
<?php
require_once 'vendor/autoload.php';
use \Firebase\JWT\JWT;
$key = "example_key"; // 秘钥
$issuedAt = time();
$expirationTime = $issuedAt + 3600; // JWT 过期时间 1 小时
$payload = array(
"iat" => $issuedAt, // 签发时间
"exp" => $expirationTime, // 过期时间
"sub" => 1234567890, // 用户ID
"name" => "John Doe",
);
$jwt = JWT::encode($payload, $key); // 生成 JWT 令牌
echo "JWT Token: " . $jwt . "\n";
?>
解释:
iat
(Issued At):签发时间,表示令牌的创建时间。exp
(Expiration Time):过期时间,表示令牌何时过期。sub
(Subject):JWT 的主题,通常是用户的 ID 或者其它标识。name
:用户的名字(自定义字段)。
5. PHP 解析和验证 JWT 令牌
解析和验证 JWT 令牌的过程,主要是通过对 JWT 令牌进行解码,并验证签名是否正确。
验证 JWT 令牌的示例代码
<?php
require_once 'vendor/autoload.php';
use \Firebase\JWT\JWT;
$key = "example_key"; // 秘钥
$jwt = $_GET['jwt']; // 获取前端传过来的 JWT 令牌
try {
// 解码 JWT 令牌并验证
$decoded = JWT::decode($jwt, $key, array('HS256'));
// 输出解码后的信息
print_r($decoded);
} catch (Exception $e) {
// 捕获异常,输出错误信息
echo 'Caught exception: ', $e->getMessage(), "\n";
}
?>
解释:
JWT::decode($jwt, $key, array('HS256'))
:通过秘钥$key
和指定的签名算法(如HS256
)解码 JWT 令牌。解码成功后返回一个 PHP 对象,包含有效载荷部分的数据。- 如果令牌无效或已过期,
decode()
方法将抛出异常,可以捕获并处理。
6. JWT 的使用场景
- 用户认证:JWT 可以用于实现基于令牌的认证机制。在用户登录时,服务器生成 JWT 令牌并返回给客户端。之后客户端每次请求时将 JWT 令牌作为请求头的一部分发送,服务器验证该令牌是否合法并返回相应的资源。
- 无状态认证:JWT 令牌包含了用户的身份信息,服务器无需保存会话数据。这使得服务器端可以是无状态的,适合于分布式系统或微服务架构。
- API 安全:JWT 可以通过 HTTPS 协议传输,确保数据的安全性。它常用于 RESTful API 的身份认证。
- 单点登录(SSO):JWT 可以在多个系统之间共享认证信息,用于实现单点登录(SSO)机制。
7. 总结
在 PHP 中处理 JWT 令牌的完整流程包括生成令牌、解析令牌和验证签名。JWT 是一种轻量级的身份验证机制,它不依赖于服务器端存储会话数据,非常适合分布式系统和微服务架构。
- 生成 JWT 令牌:通过 Firebase JWT 等库生成带有有效载荷和签名的 JWT 令牌。
- 解析和验证 JWT 令牌:验证令牌的签名,确保令牌的完整性和有效性。
- 常见应用:JWT 常用于用户认证、API 安全、单点登录等场景。
通过使用 JWT,可以更好地实现分布式系统中的身份认证和信息交换,同时减轻服务器的存储压力,提升性能和扩展性。