PHP如何实现JWT认证?

2025-12发布17次浏览

JWT(JSON Web Tokens)是一种用于双方之间传递安全可靠信息的简洁的、URL安全的表达方式。它适用于需要从一个服务器安全地传输信息到另一个服务器的场景,比如用户验证。在PHP中实现JWT认证主要涉及以下几个步骤:

  1. 生成JWT头部:JWT头部通常包含两个部分:alg(算法类型)和typ(令牌类型)。例如,使用HS256算法的头部可能是{"alg":"HS256","typ":"JWT"}

  2. 生成JWT载荷:载荷部分包含了要传递的数据,这些数据是JSON格式的。例如,可以包含用户ID、用户名等信息。

  3. 签名JWT:使用头部指定的算法和密钥对头部和载荷进行签名,以验证其完整性。在PHP中,可以使用openssl扩展来生成签名。

  4. 生成最终的JWT:将头部、载荷和签名使用.连接起来,形成一个JWT。

  5. 发送JWT到客户端:将生成的JWT发送给客户端,客户端可以在后续的请求中使用这个JWT作为身份验证的凭据。

  6. 验证JWT:当客户端发送请求到服务器时,服务器需要验证JWT的有效性,这通常包括检查签名是否正确,以及验证令牌是否过期。

下面是一个简单的PHP示例,展示如何生成和验证JWT:

<?php

// 生成JWT
function generateJWT($payload, $secretKey, $alg = 'HS256') {
    $header = json_encode(['alg' => $alg, 'typ' => 'JWT']);
    $payload = json_encode($payload);

    // 使用HS256算法进行签名
    if ($alg == 'HS256') {
        $signature = hash_hmac('sha256', $header . "." . $payload, $secretKey, true);
    }

    // 将头部、载荷和签名使用`.`连接起来
    $jwt = $header . "." . $payload . "." . base64_encode($signature);

    return $jwt;
}

// 验证JWT
function validateJWT($jwt, $secretKey, $alg = 'HS256') {
    $parts = explode('.', $jwt);
    if (count($parts) != 3) {
        return false;
    }

    $header = json_decode(base64_decode($parts[0]), true);
    $payload = json_decode(base64_decode($parts[1]), true);

    // 重新生成签名
    $signature = '';
    if ($alg == 'HS256') {
        $signature = hash_hmac('sha256', $parts[0] . "." . $parts[1], $secretKey, true);
    }

    // 验证签名
    if (base64_encode($signature) != $parts[2]) {
        return false;
    }

    // 验证载荷中的exp字段
    if (isset($payload['exp']) && time() > $payload['exp']) {
        return false;
    }

    return $payload;
}

// 使用示例
$secretKey = 'my_secret_key';
$payload = ['user_id' => 1, 'username' => 'example_user', 'exp' => time() + 3600]; // 1小时后过期

$jwt = generateJWT($payload, $secretKey);
echo "Generated JWT: " . $jwt . "\n";

$validatedPayload = validateJWT($jwt, $secretKey);
if ($validatedPayload) {
    echo "JWT is valid. Payload: ";
    print_r($validatedPayload);
} else {
    echo "JWT is invalid.";
}