php实现单点登陆
PHP实现单点登录(SSO)的方法
单点登录(SSO)允许用户通过一次登录访问多个系统。以下是基于PHP的实现方案:
基于Token的SSO实现
-
生成Token 用户登录后生成唯一Token并存储至数据库或缓存中:
$token = bin2hex(random_bytes(32)); $_SESSION['sso_token'] = $token; // 存储至数据库 $stmt = $pdo->prepare("INSERT INTO sso_tokens (user_id, token) VALUES (?, ?)"); $stmt->execute([$user_id, $token]); -
跨域共享Token 通过子域Cookie或前端传递实现:
// 设置跨域Cookie(需相同顶级域名) setcookie('sso_token', $token, time()+3600, '/', '.example.com'); -
验证Token 子系统通过接口验证Token有效性:
$token = $_COOKIE['sso_token'] ?? ''; $stmt = $pdo->prepare("SELECT user_id FROM sso_tokens WHERE token = ?"); $stmt->execute([$token]); $user = $stmt->fetch();
基于OAuth2的实现
-
授权服务器配置 使用
league/oauth2-server库:use League\OAuth2\Server\AuthorizationServer; $server = new AuthorizationServer( $clientRepository, $accessTokenRepository, $scopeRepository, $privateKey, $encryptionKey ); -
获取授权码 用户登录后重定向至授权端点:
header("Location: https://sso.example.com/auth?response_type=code&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL"); -
交换访问令牌 子系统用授权码获取令牌:
$response = $http->post('https://sso.example.com/token', [ 'grant_type' => 'authorization_code', 'code' => $_GET['code'], 'client_id' => CLIENT_ID, 'client_secret' => CLIENT_SECRET ]);
基于JWT的实现
-
生成JWT令牌 使用
firebase/php-jwt库:use Firebase\JWT\JWT; $payload = [ 'iss' => 'sso-server', 'sub' => $user_id, 'exp' => time() + 3600 ]; $jwt = JWT::encode($payload, SECRET_KEY, 'HS256'); -
验证JWT 子系统验证令牌有效性:
try { $decoded = JWT::decode($jwt, SECRET_KEY, ['HS256']); $user_id = $decoded->sub; } catch (Exception $e) { // 处理无效令牌 }
实现注意事项
- 确保所有通信使用HTTPS加密
- Token需设置合理过期时间
- 实现全局注销机制,清除所有系统的会话
- 考虑使用Redis集中存储Token以提高性能
完整示例流程
- 用户访问system1.example.com
- 未登录时重定向至sso.example.com/login
- 登录成功后生成Token并重定向回原系统
- system1通过Token获取用户信息建立本地会话
- 用户访问system2.example.com时自动通过共享Token完成登录
以上方案可根据实际需求组合使用,OAuth2适合第三方系统集成,而Token/JWT方案更适合内部系统SSO实现。







