介绍:为什么在 PHP 中需要 OAuth 2.0 和 JWT
现代 Web 应用程序很少孤立运行。用户期望通过 Google、Facebook 或 GitHub 进行单点登录,而开发者则期望在微服务之间安全地交换数据。两个关键协议——OAuth 2.0(授权委托)和 JWT(紧凑型令牌格式)——已成为事实上的标准。在本文中,我们将从头开始讲解如何使用 PHP 实现 OAuth 2.0 和 JWT 认证,仅使用语言内置功能和流行库。您将获得用于集成外部提供商和创建自己的身份验证系统的现成代码示例。
1. OAuth 2.0 基础:流程和角色
OAuth 2.0 是一种授权协议,允许第三方应用程序在不传输密码的情况下获得对用户资源的有限访问权限。它涉及四个角色:
- Resource Owner — 拥有数据的用户。
- Client — 您的 PHP 应用程序,请求访问权限。
- Authorization Server — 颁发令牌的服务器(例如 Google)。
- Resource Server — 根据令牌提供数据的 API。
Web 应用程序最流行的流程是 Authorization Code Grant。它是安全的,因为令牌通过服务器端传输,而不是通过浏览器。让我们看看如何在 PHP 中实现它。
1.1. 注册应用程序并获取 Client ID/Secret
在编写代码之前,请向提供商注册您的应用程序(例如,在 Google Cloud Console 中)。您将获得 client_id 和 client_secret,并配置重定向 URI(例如,https://your-site.com/callback.php)。
1.2. 在 PHP 中实现 Authorization Code 流程
让我们创建两个文件:login.php(重定向到授权服务器)和 callback.php(处理响应)。
文件 login.php
<?php
session_start();
$client_id = 'YOUR_CLIENT_ID';
$redirect_uri = 'https://your-site.com/callback.php';
$state = bin2hex(random_bytes(16)); // 防止 CSRF
$_SESSION['oauth_state'] = $state;
$params = http_build_query([
'client_id' => $client_id,
'redirect_uri' => $redirect_uri,
'response_type' => 'code',
'scope' => 'openid email profile',
'state' => $state,
]);
header('Location: https://accounts.google.com/o/oauth2/v2/auth?' . $params);
exit;
?>
文件 callback.php
<?php
session_start();
// 检查 state (CSRF)
if ($_GET['state'] !== $_SESSION['oauth_state']) {
die('错误:无效的 state');
}
$client_id = 'YOUR_CLIENT_ID';
$client_secret = 'YOUR_CLIENT_SECRET';
$redirect_uri = 'https://your-site.com/callback.php';
// 将代码交换为令牌
$ch = curl_init('https://oauth2.googleapis.com/token');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'code' => $_GET['code'],
'client_id' => $client_id,
'client_secret' => $client_secret,
'redirect_uri' => $redirect_uri,
'grant_type' => 'authorization_code',
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
$access_token = $data['access_token'] ?? null;
// 获取用户资料
$ch = curl_init('https://www.googleapis.com/oauth2/v2/userinfo');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $access_token]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$userInfo = json_decode(curl_exec($ch), true);
curl_close($ch);
echo '你好,' . htmlspecialchars($userInfo['email']);
?>
重要:始终检查 state 参数。它可以防止请求伪造 (CSRF)。