php实现sso需先明确跨域场景:同域名子目录用原生session即可;跨子域(如app1.example.com与app2.example.com)才需共享session存储(推荐redis)、设cookie_domain为.example.com、全站https,并严格校验jwt的iss/exp/signature;登出须中心化失效所有token。

PHP 实现 SSO 不是靠“学教程”堆出来的,而是要先分清你面对的是哪类跨域场景,再选对应路径。直接抄 session_start() 或扔一个 JWT 库进去,90% 会卡在登录后跳转子域就掉身份。
判断你是不是真需要跨子域 SSO
很多项目根本不需要 SSO,只是多个子目录(如 /admin、/api)跑在同一域名下,这种用 PHP 原生 session 就够了,不用折腾 cookie domain 或 Redis 共享。只有当你的应用分布在 app1.example.com、app2.example.com 这类不同二级域名时,才真正触发 SSO 问题。
- 检查当前所有应用的域名:是否共用同一主域(如都带
.example.com)?不是就别碰session.cookie_domain - 确认 HTTPS 是否全站启用:Chrome 120+ 已强制要求
SecureCookie 才能在跨子域生效,HTTP 下设.example.com会被静默丢弃 - 别被“统一登录页”误导:只要登录页和业务页同域,其他系统仍需各自校验,不等于自动 SSO
跨子域必须改掉默认 session 存储
PHP 默认把 session 存文件里,app1 和 app2 各自写各自的 /tmp,即使 cookie 共享了,$_SESSION 仍是空的。必须切到共享后端。
- 用 Redis 最稳妥:
session.save_handler = redis,且所有应用配置完全一致的session.save_path = "tcp://127.0.0.1:6379?auth=xxx" - 别用 Memcached:它不支持原子性的 session expire 更新,多请求并发时容易误判过期
- 如果只能用文件存储,必须确保所有应用运行在同一个用户下(如都是
www-data),否则权限错导致 session 写入失败但无报错 -
session.cookie_domain必须设为.example.com(开头带点),不能是example.com或www.example.com
JWT 方案里 $_SESSION 还要不要用
要,但角色彻底变了:它只管当前应用的临时状态,比如表单防重放的 csrf_token,或者用户刚上传未提交的草稿 ID。真正的身份认证必须交给中心签发的 JWT。
- JWT 必须校验三要素:
iss(签发方域名)、exp(绝对过期时间)、signature(用私钥验签),缺一不可 - 别把
password_hash、手机号塞进 JWT payload——Base64 不是加密,前端 localStorage 里一查就露馅 - Cookie 存 JWT 时,
SameSite=None; Secure缺一不可,否则跨子域请求浏览器压根不发 - 刷新 Token 必须走独立接口(如
/auth/refresh),且旧 token 签发后立刻从 Redis 黑名单中注销,不能等自然过期
最常被忽略的其实是登出逻辑:用户在 app1 点退出,app2 的 JWT 还在 localStorage 里,下次访问照样能过。必须让登出请求同步调用中心服务,把该用户的全部有效 token 标记为失效——这个动作比登录难十倍,但没人提。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











