在 PHP 中,JWT(JSON Web Token) 是一种常用的用于身份验证和信息交换的令牌格式。JWT 通常包含三部分:头部、有效载荷和签名。通过签名验证,可以确保令牌的完整性和有效性。PHP 中处理 JWT 令牌的完整流程包括生成令牌、解析令牌和验证令牌。

目录

  1. 什么是 JWT(JSON Web Token)
  2. JWT 的结构
    • 2.1 头部(Header)
    • 2.2 有效载荷(Payload)
    • 2.3 签名(Signature)
  3. PHP 中处理 JWT 的常见库
  4. PHP 生成 JWT 令牌
  5. PHP 解析和验证 JWT 令牌
  6. JWT 的使用场景
  7. 总结

1. 什么是 JWT(JSON Web Token)

JWT 是一种基于 JSON 的开放标准(RFC 7519),用于在网络应用环境间以可验证的方式安全地传输声明。JWT 通常用于实现 无状态的身份验证,并且广泛应用于 Web 应用程序和移动应用程序中。

JWT 的一个典型应用场景是通过 API 提供身份验证,尤其是在分布式系统中,服务器不需要存储状态信息,只需要验证 JWT 的合法性即可。


2. JWT 的结构

JWT 由三部分组成:

  1. 头部(Header):指定令牌的类型(通常是 JWT)以及所使用的签名算法(如 HMAC SHA256 或 RSA)。
  2. 有效载荷(Payload):包含声明(Claims)。声明是关于实体(通常是用户)和额外数据的信息。JWT 中有三种类型的声明:
    • 注册声明(Registered Claims):如 iss(发行者)、exp(过期时间)等。
    • 公共声明(Public Claims):可以自定义的声明。
    • 私有声明(Private Claims):由双方自定义的声明,通常用于交换特定数据。
  3. 签名(Signature):用于验证令牌的完整性,确保令牌未被篡改。签名由头部、有效载荷和一个密钥(如 HMAC SHA256)共同生成。

JWT 令牌的格式如下:

header.payload.signature

2.1 头部(Header)

头部通常由两部分组成:

  • typ:JWT(类型)。
  • alg:签名算法,常见的有 HS256RS256 等。

例如:

{
  "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 库进行演示。


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 是一种轻量级的身份验证机制,它不依赖于服务器端存储会话数据,非常适合分布式系统和微服务架构。

  1. 生成 JWT 令牌:通过 Firebase JWT 等库生成带有有效载荷和签名的 JWT 令牌。
  2. 解析和验证 JWT 令牌:验证令牌的签名,确保令牌的完整性和有效性。
  3. 常见应用:JWT 常用于用户认证、API 安全、单点登录等场景。

通过使用 JWT,可以更好地实现分布式系统中的身份认证和信息交换,同时减轻服务器的存储压力,提升性能和扩展性。