同域双应用自建PHP简易SSO方案技术合理性咨询
方案评估结论
这套实现思路能满足最基础的同域登录态传递需求,但代码本身存在大量硬错误、安全漏洞和逻辑缺陷,仅能作为本地测试的demo使用,完全不具备生产环境可用性。
现存问题
代码硬错误(直接导致功能无法正常运行)
- 令牌文件读写路径不匹配:写入令牌时用的是系统根目录路径
/[PHPSESSID].txt,读取时走的是相对路径../../appA/[PHPSESSID].txt,正常配置下根本无法读到写入的令牌文件。 - 无效函数调用:用
file_get_contents读取文件内容后,没有通过fopen获取文件句柄就直接调用fclose(),会直接抛出PHP运行警告。 - 白名单生成逻辑失效:
explode(',', "127.0.0.1","127.0.0.2")参数传递错误,explode第三个参数是结果数组长度限制,传入第二个IP字符串会导致白名单仅包含127.0.0.1,127.0.0.2不会被加入白名单。 - 数据库查询逻辑完全错误:一是SQL语句引号不匹配,表名
users前误用单引号、后用反引号,语法报错;二是解析令牌得到的变量是$token_user,查询时却使用未定义的$token_email变量,查询必然失败;三是直接拼接未经过滤的用户可控变量到SQL语句,存在SQL注入风险;四是判断逻辑app_dbNumRows($result) == true不严谨,返回非0行数都会判定为通过,重复用户数据会直接绕过校验。
安全漏洞
- 令牌无任何防伪造能力:直接将客户端可获取的
PHPSESSID和明文用户名拼接作为令牌,没有签名、没有加密,攻击者只要猜到有效PHPSESSID就能伪造任意用户身份。 - 令牌文件存在泄露风险:如果没有额外配置目录访问规则,令牌文件可能被攻击者通过目录遍历、web路径直接下载,泄露所有用户的登录凭证。
- Cookie安全配置缺失:下发
CookieToken时仅设置了Secure属性,缺少HttpOnly(防止XSS窃取Cookie)、SameSite(防止CSRF攻击)属性,且CookieToken值直接等于PHPSESSID,一旦被窃取直接导致账号被盗。 - 校验逻辑绕过风险:header.php中的登录态判断用了
&&逻辑,即「令牌文件不存在 且 PHPSESSID不等于CookieToken才拦截」,意味着攻击者只要手动把CookieToken的值改成和当前PHPSESSID一致,哪怕令牌文件已经被删除,也能绕过校验保持登录。 - 无用户身份绑定校验:校验令牌时只判断文件是否存在、
PHPSESSID是否匹配,没有校验令牌中存储的用户名和当前要登录的用户是否一致,存在越权登录可能。
设计缺陷
- 单点登出不完整:登出时仅删除了服务端的令牌文件,没有主动失效根域名下的
CookieToken,也没有同步清理两个应用的本地会话,用户可能在应用B侧保持登录状态。 - 过期清理逻辑不可靠:靠用户访问被动触发24小时过期文件清理,访问量低时过期文件会长期残留,高并发下多个请求同时触发清理还会产生文件读写冲突,甚至误删有效令牌。
- 文件存储性能差:高并发场景下用txt文件做存储会存在读写锁竞争问题,多个请求同时读写同一个令牌文件会导致内容损坏、校验失败。
优化方向
- 先修复所有代码硬错误:统一令牌文件的存储路径(建议放到非web可访问的目录),修正函数调用、参数传递、SQL语句的语法错误,所有数据库操作改用预处理语句,禁止直接拼接用户可控参数。
- 重构令牌生成逻辑:不要直接用
PHPSESSID作为令牌,使用服务端存储的专用密钥,通过hash_hmac等算法生成带签名的令牌,令牌内容包含用户ID、过期时间、客户端特征指纹(如UA片段、IP段),校验时先验证签名合法性,再校验过期时间、用户身份、客户端特征,所有校验逻辑的核心因子不能暴露在客户端。 - 替换存储介质:放弃txt文件存储,改用Redis、关系型数据库等成熟存储方案,天然支持键值过期、并发安全,不需要自行实现过期清理逻辑,稳定性提升明显。如果是极简同域场景,甚至可以直接把两个应用的PHP会话存储配置为共享、会话Cookie的域名设置为根域名,直接复用原生会话即可,不需要额外开发令牌逻辑。
- 完善Cookie安全配置:所有认证相关Cookie必须同时添加
Secure、HttpOnly、SameSite=Lax/Strict属性,CookieToken不要直接存PHPSESSID,而是和服务端存储的已签名令牌做绑定校验,不要信任客户端传入的Cookie值做相等判断。 - 修正登录态校验逻辑:把校验条件的
&&改为||,只要令牌不存在、令牌校验不通过、Cookie和服务端记录不匹配任意一个条件满足,就判定为未登录,拦截请求。 - 完善单点登出逻辑:登出时除了删除服务端令牌,还要立刻将根域名下的所有认证Cookie设置为过期,两个应用的所有请求都要实时校验服务端令牌的有效性,不要仅依赖本地Cookie判断登录态。
内容的提问来源于stack exchange,提问作者user9289016
相关产品推荐
相关产品推荐

