php 实现单点登录
PHP 实现单点登录的方法
单点登录(SSO)允许用户通过一次登录访问多个相互信任的系统。以下是基于 PHP 的实现方案:
基于共享 Session 的方案
在同一个主域名下的子域名间可以通过共享 Session 实现 SSO。PHP 默认情况下 Session 的 Cookie 作用域是当前域名,可以通过修改 session.cookie_domain 配置实现跨子域名共享。
// 设置 Session Cookie 的作用域为 .example.com
ini_set('session.cookie_domain', '.example.com');
session_start();
各个子域名的应用需要统一 Session 存储,例如使用 Redis 作为共享存储:
ini_set('session.save_handler', 'redis');
ini_set('session.save_path', 'tcp://127.0.0.1:6379');
基于 Token 的方案
对于跨域场景,可以使用 Token 方案。认证中心颁发 Token,各应用系统验证 Token 的有效性。
- 用户访问系统 A,未登录则跳转至认证中心
- 认证中心验证用户身份,生成 Token 并重定向回系统 A
- 系统 A 携带 Token 向认证中心验证
- 认证通过后建立本地 Session
Token 生成示例:
function generateToken($userId) {
$secret = 'your_secret_key';
$header = base64_encode(json_encode(['alg' => 'HS256', 'typ' => 'JWT']));
$payload = base64_encode(json_encode(['user_id' => $userId, 'exp' => time() + 3600]));
$signature = hash_hmac('sha256', "$header.$payload", $secret);
return "$header.$payload.$signature";
}
基于 OAuth 2.0 的方案
OAuth 2.0 是标准的授权协议,可用于实现 SSO。常用库包括 league/oauth2-client。
安装库:
composer require league/oauth2-client
客户端实现示例:
use League\OAuth2\Client\Provider\GenericProvider;
$provider = new GenericProvider([
'clientId' => 'your_client_id',
'clientSecret' => 'your_client_secret',
'redirectUri' => 'https://your-app.com/callback',
'urlAuthorize' => 'https://sso-provider.com/authorize',
'urlAccessToken' => 'https://sso-provider.com/token',
'urlResourceOwnerDetails' => 'https://sso-provider.com/resource'
]);
// 获取授权码
if (!isset($_GET['code'])) {
$authUrl = $provider->getAuthorizationUrl();
$_SESSION['oauth2state'] = $provider->getState();
header('Location: '.$authUrl);
exit;
}
// 获取访问令牌
try {
$accessToken = $provider->getAccessToken('authorization_code', [
'code' => $_GET['code']
]);
// 使用令牌获取用户信息
$resourceOwner = $provider->getResourceOwner($accessToken);
$user = $resourceOwner->toArray();
// 建立本地会话
$_SESSION['user'] = $user;
} catch (\Exception $e) {
exit('登录失败: '.$e->getMessage());
}
基于 SAML 的方案
SAML 是企业级 SSO 常用协议,可使用 simplesamlphp 库实现。
安装 SimpleSAMLphp:
composer require simplesamlphp/simplesamlphp
配置 SP (Service Provider):
require_once('vendor/simplesamlphp/lib/_autoload.php');
$auth = new SimpleSAML_Auth_Simple('default-sp');
if (!$auth->isAuthenticated()) {
$auth->login();
}
$attributes = $auth->getAttributes();
$_SESSION['user'] = $attributes;
安全注意事项
- 所有方案都应使用 HTTPS 确保传输安全
- Token 应设置合理的过期时间
- 敏感操作需要重新验证
- 实现完善的注销机制,包括各系统的会话清除
注销实现
全局注销需要清除所有系统的会话:
// 认证中心注销
session_destroy();
// 通知各子系统注销
foreach ($subSystems as $system) {
file_get_contents("$system/logout?token=$globalToken");
}
以上方案可根据实际需求选择或组合使用,企业级环境推荐 OAuth 2.0 或 SAML 方案。






