























AI 概述
本文阐述企业多系统引入SSO单点登录的必要性,讲解中心化SSO基于Ticket票据的完整认证流程,并基于Yii2(PHP)给出可落地实现方案:分层定义SSO接口、对接服务、登录回调控制器,自动同步本地用户。同时提出生产环境三大安全防护要点,防范票据重放、权限泄露、数据伪造风险。
目录
文章目录隐藏

在企业级应用群落中,孤立的账号体系是研发和用户的噩梦。当公司内部孵化出 OA、CRM、ERP 等多套系统时,如果用户在每个系统都需要重复输入账号密码,不仅体验极差,数据孤立、权限混乱、安全防线难以收拢等痛点也会接踵而至。
SSO(Single Sign-On,单点登录) 正是解决这一痛点的终极方案。它允许用户在多个互信的独立业务系统中,“一次登录,到处通行”。本文将带你从底层机制出发,用 PHP (Yii2 架构) 闭环实现一套工业级的 SSO 接入方案。
要接入 SSO,首先必须搞懂它的核心账密置换凭证 —— Ticket(授权码/票据)机制。
我们以经典的中心化认证流为例,当用户访问受保护的业务系统时,其核心步骤如下:
为了让代码更具规范性和扩展性,我们采用 接口定义 服务实现 控制器调用 的三层架构。
首先,我们定义一个规范的接口。不论未来的 SSO 协议是基于标准的 OIDC、OAuth2 还是自研的 CAS,业务层只需要关心这两个核心动作。
<?php
namespace app\components\sso;
interface SSOLoginInterface
{
/**
* 获取单点登录中心授权跳转地址
* @return string 跳转到 SSO 中心的完整 URL
*/
public function getAuthUrl(): string;
/**
* 通过回调获得的 Ticket 换取 SSO 中心的用户信息
* @param string $ticket 认证票据
* @return array 用户基础信息数组
* @throws \Exception 校验失败时抛出异常
*/
public function getInfoFromTicket(string $ticket): array;
}
这里我们模拟一个具体的 CompanySSOService。在实际生产环境下,你可以将这里的 curl 请求替换为你们公司的 SSO 中心真实 API。
<?php
namespaceapp\components\sso;
useYii;
useyii\base\Component;
class CompanySSOService extends Component implements SSOLoginInterface
{
public $ssoHost = 'https://sso.company.com';
public $clientId = 'crm_system_01';
public $clientSecret = 'sso_secret_key_xxxxxx';
publicfunction getAuthUrl(): string
{
// 告诉 SSO 中心,认证成功后跳回本地的什么地方
$callbackUrl = urlencode(Yii::$app->request->getHostInfo() . '/sso/callback');
return"{$this->ssoHost}/login?client_id={$this->clientId}&redirect_uri={$callbackUrl}";
}
publicfunction getInfoFromTicket(string $ticket): array
{
$apiExhangeUrl = "{$this->ssoHost}/api/verify-ticket";
// 发起后端安全的 Server to Server 请求,杜绝前端伪造
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiExhangeUrl);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'ticket' => $ticket,
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
]));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
if (empty($result) || !isset($result['success']) || !$result['success']) {
thrownew \Exception("SSO 凭证校验失败: " . ($result['message'] ?? '未知错误'));
}
return $result['data']; // 返回格式统一包含: username, email, truename
}
}
在 Yii2 框架中创建 SsoController。它是整个登录闭环的控制中枢,负责处理 Ticket 的接收、新用户的自动常驻同步、以及本地会话的建立。
<?php
namespaceapp\controllers;
useYii;
useyii\web\Controller;
useyii\web\BadRequestHttpException;
useapp\models\User;
useapp\components\sso\CompanySSOService;
class SsoController extends Controller
{
/**
* @return CompanySSOService
*/
privatefunction getSsoService()
{
// 建议在 Yii 的 components 中配置注入,此处快速实例化演示
returnnew CompanySSOService();
}
/**
* 登录入口触发表
*/
publicfunction actionLogin()
{
// 如果本地已经有登录态,直接去后台首页
if (!Yii::$app->user->isGuest) {
return$this->redirect(['/dashboard']);
}
// 渲染登录引导页,将前端登录按钮的链接指向 SSO 授权页
return$this->render('login', [
'ssoUrl' => $this->getSsoService()->getAuthUrl()
]);
}
/**
* SSO 中心认证通过后的核心回调接口
*/
publicfunction actionCallback()
{
$ticket = Yii::$app->request->get('ticket');
if (empty($ticket)) {
thrownew BadRequestHttpException('授权失败:缺失关键 ticket 参数');
}
try {
// 1. 去 SSO 中心洗白,拿回用户的真实资料
$ssoUser = $this->getSsoService()->getInfoFromTicket($ticket);
if (empty($ssoUser['username'])) {
return$this->renderError('SSO 授信中心返回的用户数据不完整');
}
// 2. 统一格式规整(防止大小写引发的账号双胞胎问题)
$username = strtolower(trim($ssoUser['username']));
// 3. 检索本地账号仓库,不存在则自动激活“影子上游账号”
$user = User::find()->where(['username' => $username])->one();
if (!$user) {
$user = new User();
$user->username = $username;
$user->email = $ssoUser['email'] ?? "{$username}@company.com";
$user->realname = $ssoUser['truename'] ?? '新员工';
$user->role = User::ROLE_MEMBER; // 默认赋予普通成员权限
$user->status = User::STATUS_ACTIVE;
if (!$user->save()) {
thrownew \Exception("本地同步创建用户失败:" . json_encode($user->getErrors()));
}
}
// 4. 正式签发本地登录会话(Session/Cookie 保持 30 天)
Yii::$app->user->login($user, 3600 * 24 * 30);
// 5. 顺滑流转至系统内部首页
return$this->redirect(['/dashboard']);
} catch (\Exception $e) {
Yii::error("SSO 登录异常挂起: " . $e->getMessage(), __METHOD__);
return$this->renderError($e->getMessage());
}
}
privatefunction renderError($msg)
{
return$this->render('error', [
'message' => $msg,
'retryUrl' => $this->getSsoService()->getAuthUrl()
]);
}
}
单点登录一旦被攻破,意味着黑客拿到了进入公司所有系统的万能钥匙。在生产环境中部署时,必须牢记以下三大安全增强准则:
通过上述的逻辑重构与代码补充,我们可以发现,PHP 在接入 SSO 时拥有天然的高效和灵活性。只要我们卡死回调接口,做好 Ticket 的后台二次验证和账号的动态同步,就可以快速让任何一个新旧 PHP 项目无缝融入到公司的全局统一账号生态中。
以上关于PHP (Yii2) 接入企业级 SSO 单点登录实战教程的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。
「点点赞赏,手留余香」
赞 1 赏
给作者打赏,鼓励TA抓紧创作!
微信
支付宝
还没有人赞赏,快来当第一个赞赏的人吧!
声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » PHP (Yii2) 接入企业级 SSO 单点登录实战教程
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。