如何在两个跨域站点间实现无需传递token的Web-SSO单点登录?
机制说明
你描述的场景完全有成熟的标准化实现方案,不存在所谓「反向OAuth2」的情况,OAuth2/OIDC协议本身就覆盖了这类同主体多可信客户端的SSO需求,你之前查阅的资料多为第三方客户端授权场景,没有覆盖到同主体静默授权的用法而已。
适配性说明
OAuth2完全适配你的需求,你需要用到的是OAuth2的静默授权流(核心参数prompt=none),结合iframe跨域通信逻辑即可实现,全程不会在URL传递敏感token,符合安全要求。
可选实现方案
你可以根据团队的改造接受度选择以下两种方案:
方案1:标准OAuth2静默授权(推荐,长期可扩展)
该方案符合安全标准,后续新增其他客户端时不需要额外改造鉴权核心逻辑,实现步骤如下:
- 先给共用后端扩展OAuth2授权服务能力,给外层PHP站点(站点A)、内层React SPA(站点B)分别分配唯一的客户端ID,配置两个客户端为同主体互信客户端
- 站点A的原有登录逻辑不变,用户登录成功后,后端给站点A下发带
HttpOnly、Secure属性的会话Cookie,禁止前端JS读取,避免XSS窃取 - 内层站点B初始化时,创建隐藏iframe加载OAuth2授权服务的
/oauth2/authorize端点,请求参数携带站点B的客户端ID、请求权限scope,以及关键参数prompt=none(告知授权服务不需要用户交互,直接用现有登录会话返回结果) - 授权服务收到请求后,检查当前是否存在有效的用户登录会话(即站点A登录后种下的Cookie,iframe加载授权服务域名时会自动携带该Cookie),确认会话有效且站点B为可信客户端后,直接生成一次性授权码,302跳转到站点B预先配置的回调地址
- 站点B的回调页面拿到授权码后,向后端发起请求换取AccessToken和RefreshToken,存在站点B的内存或
localStorage中即可正常调用公共API - 安全加固:回调页面拿到授权码后,可通过
postMessage将授权码传递给站点B主应用,同时校验父窗口origin为站点A的合法域名,避免授权码被恶意站点窃取
注意:如果授权服务域名和站点A域名不一致,需要将会话Cookie的
SameSite属性设置为None; Secure,确保iframe加载时可以正常携带Cookie。
方案2:轻量跨域凭证校验(适合快速上线,改造量小)
如果暂时不想改造后端支持完整OAuth2协议,可以选择该轻量方案,全程也不会在URL传递敏感信息:
- 站点A用户登录成功后,后端生成一个一次性高熵短期授权凭证,有效期控制在10秒以内,仅允许使用一次,和当前登录用户ID绑定后存入后端缓存
- 站点A在加载站点B的iframe前,先调用后端接口拿到该一次性凭证,通过
postMessage发送给iframe内的站点B,发送时指定targetOrigin为站点B的域名,避免信息泄露 - 站点B收到凭证后,立即将凭证发送给共用后端校验,后端校验凭证有效、未被使用、对应用户状态正常后,给站点B下发AccessToken,同时立刻销毁该一次性凭证防止复用
- 安全要求:
- 一次性凭证必须为32位以上的高熵随机字符串,禁止使用可预测的规则生成
- 站点B接收
postMessage时必须校验消息来源的origin为站点A的合法域名,拒绝接收未知来源的消息
方案对比
- 方案1优势:符合国际安全标准,支持后续多客户端扩展,安全能力更完善,适合中大型团队长期迭代的业务
- 方案2优势:前后端改造量极小,可快速上线,适合小团队短期需求
内容的提问来源于stack exchange,提问作者user16712441
相关产品推荐
相关产品推荐

