PHP示例
PHP 示例(原生 + cURL,无框架依赖)
php运行
<?php
/**
* 软柠通行证 OAuth 2.0 PHP 接入示例
* 依赖:PHP 7.4+、cURL 扩展
*/
// 配置信息(替换为你的实际值)
define('CLIENT_ID', 'YOUR_CLIENT_ID');
define('CLIENT_SECRET', 'YOUR_CLIENT_SECRET');
define('REDIRECT_URI', 'https://your-domain.com/callback');
define('AUTH_URL', 'https://id.rutno.com/rn-oauth/authorize');
define('TOKEN_URL', 'https://id.rutno.com/rn-oauth/token');
define('USERINFO_URL', 'https://id.rutno.com/rn-oauth/userinfo');
// 步骤1:生成授权链接(引导用户授权)
function getAuthUrl() {
// 生成随机state防CSRF
$state = bin2hex(random_bytes(16));
// 存储state到session(验证回调时使用)
session_start();
$_SESSION['oauth_state'] = $state;
$params = [
'client_id' => CLIENT_ID,
'redirect_uri' => REDIRECT_URI,
'response_type' => 'code',
'scope' => 'username email avatar',
'state' => $state
];
return AUTH_URL . '?' . http_build_query($params);
}
// 步骤2:回调处理(获取code并换token)
function handleCallback() {
session_start();
// 1. 校验state防CSRF
if (empty($_GET['state']) || $_GET['state'] !== $_SESSION['oauth_state']) {
die('State验证失败,可能是CSRF攻击');
}
// 2. 处理错误
if (!empty($_GET['error'])) {
die('授权失败:' . $_GET['error'] . ' - ' . $_GET['error_description']);
}
// 3. 获取code
if (empty($_GET['code'])) {
die('未获取到授权码');
}
$code = $_GET['code'];
// 4. 换取access_token
$token = getAccessToken($code);
if (!$token) {
die('获取Token失败');
}
// 5. 获取用户信息
$userInfo = getUserInfo($token['access_token']);
if (!$userInfo) {
die('获取用户信息失败');
}
// 6. 业务处理(示例:打印用户信息)
print_r($userInfo);
}
// 换取Access Token
function getAccessToken($code) {
$postData = [
'grant_type' => 'authorization_code',
'client_id' => CLIENT_ID,
'client_secret' => CLIENT_SECRET,
'code' => $code,
'redirect_uri' => REDIRECT_URI
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, TOKEN_URL);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/x-www-form-urlencoded'
]);
// 开启HTTPS验证(生产环境必须)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
error_log('Token请求失败,HTTP状态码:' . $httpCode);
return false;
}
$result = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE || empty($result['access_token'])) {
error_log('Token解析失败:' . $response);
return false;
}
return $result;
}
// 获取用户信息
function getUserInfo($accessToken) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, USERINFO_URL);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $accessToken
]);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
error_log('用户信息请求失败,HTTP状态码:' . $httpCode);
return false;
}
$result = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
error_log('用户信息解析失败:' . $response);
return false;
}
return $result;
}
// 入口逻辑
if (!isset($_GET['code'])) {
// 未获取到code,跳转到授权页
header('Location: ' . getAuthUrl());
} else {
// 回调处理
handleCallback();
}
?>
PHP 使用说明
- 确保开启 session、curl、openssl 扩展
- 生产环境建议增加:Token 过期自动刷新(使用 refresh_token)接口请求超时设置日志持久化存储