当前位置: 首页 > article >正文

php 实现JWT

在 PHP 中,JSON Web Token (JWT) 是一种开放标准 (RFC 7519) 用于在各方之间作为 JSON 对象安全地传输信息。JWT 通常用于身份验证系统,如 OAuth2 或基于令牌的身份验证。

以下是一个基本的 PHP 实现 JWT 生成和验证的代码示例。

JWT 的组成部分

JWT 包含三个部分:

  1. Header(头部):说明算法和令牌类型。
  2. Payload(有效载荷):包含声明(如用户数据、过期时间等)。
  3. Signature(签名):用于验证令牌是否被篡改。

JWT 格式如下:
header.payload.signature

基本步骤

  1. 编码:使用 Base64 编码 Header 和 Payload。
  2. 签名:使用 Header 中定义的算法对编码后的 Header 和 Payload 进行签名。
  3. 验证:解析 JWT 时,通过检查签名是否有效来验证令牌。

代码实现

<?php

class JWT
{
    private static $secretKey = 'your_secret_key'; // 加密使用的秘钥
    private static $algo = 'HS256';  // 使用的算法

    /**
     * 生成JWT
     * 
     * @param array $payload 数据负载
     * @return string
     */
    public static function generateJWT($payload)
    {
        // 1. 生成header
        $header = json_encode(['alg' => self::$algo, 'typ' => 'JWT']);
        $base64Header = self::base64UrlEncode($header);

        // 2. 生成payload
        $base64Payload = self::base64UrlEncode(json_encode($payload));

        // 3. 生成signature
        $signature = hash_hmac('sha256', "$base64Header.$base64Payload", self::$secretKey, true);
        $base64Signature = self::base64UrlEncode($signature);

        // 4. 组合JWT
        $jwt = "$base64Header.$base64Payload.$base64Signature";

        return $jwt;
    }

    /**
     * 验证JWT
     * 
     * @param string $token JWT令牌
     * @return array|bool 如果验证成功返回payload,否则返回false
     */
    public static function verifyJWT($token)
    {
        // 1. 拆分JWT
        $parts = explode('.', $token);
        if (count($parts) !== 3) {
            return false;
        }

        list($base64Header, $base64Payload, $base64Signature) = $parts;

        // 2. 解码Header和Payload
        $header = json_decode(self::base64UrlDecode($base64Header), true);
        $payload = json_decode(self::base64UrlDecode($base64Payload), true);
        $signature = self::base64UrlDecode($base64Signature);

        // 3. 验证签名
        $expectedSignature = hash_hmac('sha256', "$base64Header.$base64Payload", self::$secretKey, true);
        if (!hash_equals($signature, $expectedSignature)) {
            return false;
        }

        // 4. 验证过期时间
        if (isset($payload['exp']) && $payload['exp'] < time()) {
            return false;
        }

        return $payload;
    }

    /**
     * Base64URL编码
     * 
     * @param string $data
     * @return string
     */
    private static function base64UrlEncode($data)
    {
        return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
    }

    /**
     * Base64URL解码
     * 
     * @param string $data
     * @return string
     */
    private static function base64UrlDecode($data)
    {
        return base64_decode(strtr($data, '-_', '+/'));
    }
}

说明:

  1. 生成 JWT

    • 使用  generateJWT($payload)  方法生成 JWT。
    •  header  包含签名算法信息(这里使用 HS256),payload 包含用户信息或其他声明。
    • hash_hmac('sha256') 方法签名生成的 JWT。
  2. 验证 JWT

    • 使用 verifyJWT($token) 方法验证 JWT。
    • 验证签名是否正确,以及 payload 中是否设置了过期时间(可选)。
  3. Base64 编码/解码

    • 使用 base64UrlEncode() base64UrlDecode() 实现 URL 安全的 Base64 编码。

测试代码

// 测试JWT生成
$payload = [
    'user_id' => 123,
    'username' => 'john_doe',
    'exp' => time() + 3600  // 过期时间1小时
];

$jwt = JWT::generateJWT($payload);
echo "Generated JWT: " . $jwt . PHP_EOL;

// 测试JWT验证
$decodedPayload = JWT::verifyJWT($jwt);
if ($decodedPayload) {
    echo "JWT is valid! Payload: " . print_r($decodedPayload, true) . PHP_EOL;
} else {
    echo "Invalid JWT!" . PHP_EOL;
}

JWT 生成结果示例

Generated JWT: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJ1c2VyX2lkIjogMTIzLCAidXNlcm5hbWUiOiAiam9obl9kb2UiLCAiZXhwIjogMTYxNjg1MjIwMn0.J0wLkhlUkTftKzVzR7Y9pVwSBU-WESCTwks2FyUwDUU
JWT is valid! Payload: Array
(
    [user_id] => 123
    [username] => john_doe
    [exp] => 1616852202
)

说明:

  • 过期时间 exp:你可以在 payload 中加入 exp,它代表 JWT 过期的时间戳,通常用来限制令牌的有效期。
  • 签名算法:这里使用的是 HS256(HMAC-SHA256),你可以根据需求换成其他的对称或非对称签名算法。

应用场景

  1. 用户认证:基于 JWT 的用户登录、身份验证机制。
  2. API 授权:通过 JWT 传递身份验证信息,允许或拒绝 API 请求。
  3. 微服务间通信:在分布式系统中,JWT 可以用于服务之间的身份验证和授权。

http://www.kler.cn/a/304401.html

相关文章:

  • Confluent Cloud Kafka 可观测性最佳实践
  • UE5 渲染管线 学习笔记
  • Naive UI 多选框自定义tag和label
  • webrtc获取IceCandidate流程
  • LeetCode 343.整数拆分
  • 第十四章 C++ 数字
  • 用于客户支持的 GenAI:探索 Elastic Support Assistant
  • 如何让Windows控制台窗口不接受鼠标点击(禁用鼠标输入)
  • 前端工程师职业发展路线图
  • MADE A PIE 之动态树形图
  • 解决Docker镜像不可下载
  • 【GBase 8c V5_3.0.0 分布式数据库常用几个SQL】
  • 使用 Node Media Server 和 FFmpeg 创建直播流,推送本地视频
  • 在 Mac 上安装双系统会影响性能吗,安装双系统会清除数据吗?
  • 使用VSCode 安装SAP Fiori 开发所需插件
  • el-tree父子不互相关联时,手动实现全选、反选、子级全选、清空功能
  • Qt 构建报错 undefined reference to xxx
  • C++字符串中的string类操作
  • Humanize AI 简介
  • C和指针:函数
  • Leetcode 701-二叉搜索树中的插入操作
  • 安卓开发板_联发科MTK开发板使用ADB开发
  • Excel--不规则隔行填充底纹颜色
  • 【动手学深度学习】08 线性回归 + 基础优化算法(个人向笔记)
  • SpringCloud神领物流学习笔记:项目概述(一)
  • 计算机网络 ---如何寻找目标计算机