OAuth 2.0 和 JWT 授权在 PHP 中的实现:初学者完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

PHP 中的 OAuth 2.0 和 JWT 简介

\n\n

现代 Web 应用程序很少能脱离授权系统。两种最流行的协议——OAuth 2.0 和 JWT(JSON Web Token)——使开发人员能够创建安全且可扩展的解决方案。在本文中,我们将详细讲解如何从零开始在 PHP 中实现 OAuth 2.0 和 JWT 授权。本材料面向初学者,因此所有概念都将用通俗易懂的语言配合实际示例进行解释。

\n\n

OAuth 2.0 是一种委托访问协议。它允许用户向第三方授予对其资源的有限访问权限,而无需传递密码。而 JWT 是一种紧凑的令牌格式,其中包含有关用户及其权限的所有必要信息。

\n\n

什么是 JWT 以及它是如何工作的?

\n\n

JWT(JSON Web Token)是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,以 JSON 对象的形式在各方之间传输信息。令牌由三部分组成,用点分隔:

\n\n
    \n
  • Header(头部)——包含有关令牌类型和加密算法的信息(通常为 HS256 或 RS256)。
  • \n
  • Payload(载荷)——包含“声明”(claims):用户数据、签发时间(iat)、过期时间(exp)等。
  • \n
  • Signature(签名)——基于头部、载荷和密钥创建的签名。保证数据的完整性。
  • \n
\n\n

典型的 JWT 如下所示:

\n\n
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6ItCQ0L3QsNGC0L7Qu9C40LkiLCJpYXQiOjE1MTYyMzkwMjJ9.4vGJ7qF6b0Q9l8z3X5p2Rk1h7t9y2w4z6x8c0v2b4n6m8
\n\n

JWT 的优势在于服务器无需在数据库中存储会话——所有信息都已编码在令牌中。这使得系统易于扩展。

\n\n

安装用于在 PHP 中处理 JWT 的库

\n\n

为了在 PHP 中处理 JWT,我们将使用流行的库 firebase/php-jwt。通过 Composer 安装它:

\n\n
composer require firebase/php-jwt
\n\n

创建和验证 JWT 令牌

\n\n

让我们看一个基本示例:用户登录时创建令牌,并在请求受保护资源时验证令牌。

\n\n

1. 生成令牌(login.php):

\n\n
<?php\nrequire_once 'vendor/autoload.php';\n\nuse Firebase\\JWT\\JWT;\nuse Firebase\\JWT\\Key;\n\n$secretKey = '您的密钥-长度不少于32个字符';\n\n// 成功身份验证后的用户数据\n$payload = [\n    'iss' => 'pythonlib.ru',        // 令牌签发者\n    'sub' => $userId,              // 用户 ID\n    'name' => $userName,           // 用户名\n    'role' => 'user',              // 角色\n    'iat' => time(),               // 签发时间\n    'exp' => time() + 3600         // 令牌1小时后过期\n];\n\n$jwt = JWT::encode($payload, $secretKey, 'HS256');\n\n// 将令牌发送给客户端\necho json_encode(['token' => $jwt]);\n?>
\n\n

2. 验证令牌(profile.php):

\n\n
<?php\nrequire_once 'vendor/autoload.php';\n\nuse Firebase\\JWT\\JWT;\nuse Firebase\\JWT\\Key;\n\n$secretKey = '您的密钥-长度不少于32个字符';\n\n// 从 Authorization 头部获取令牌\n$headers = getallheaders();\n$authHeader = $headers['Authorization'] ?? '';\n\nif (preg_match('/Bearer\\s(\\S+)/', $authHeader, $matches)) {\n    $jwt = $matches[1];\n    \n    try {\n        $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256'));\n        \n        // 令牌有效,获取用户数据\n        $userId = $decoded->sub;\n        $userName = $decoded->name;\n        \n        // 返回受保护的数据\n        echo json_encode(['status' => 'success', 'user' => $decoded]);\n        \n    } catch (Exception $e) {\n        // 令牌无效或已过期\n        htt                

博客

书籍推荐