在多个域名之间做网页授权,统一登录的核心方案是搭建中心化认证平台,各业务域名通过跳转携带ticket换取登录态,再配合跨域共享Cookie或前端postMessage同步登录信息,权限管理则统一在认证平台侧配置。
多域名网页授权的痛点:Cookie被浏览器隔离
很多开发者在处理多域名登录时,第一反应是沿用单域名下的Session方案,但浏览器出于安全策略,默认不允许跨域读写Cookie,比如用户在 a.com 登录成功后,跳转到 b.com,b.com 拿不到 a.com 种下的Cookie,用户状态自然丢失,这就是最核心的冲突。
具体到业务场景中,常见的情况有两种,一种是主站和子站用了不同的一级域名,example.com 和 goods.net,这种是彻底跨域,另一种是多个二级子域名,shop.example.com 和 user.example.com,虽然可以通过设置 domain=example.com 让Cookie共享,但实践中会发现,如果某个二级域名需要对接公众号网页授权或者第三方支付回调,这种方案就会碰到瓶颈,第三方平台只会往它们配置的指定域名写Cookie,不会帮你往父域名同步。
统一登录的三种主流实现路径
跳转中转方案:最通用、兼容性最强
这套思路是最接近OAuth 2.0授权码模式的轻量级实践,核心逻辑是:
- 用户在
a.com点击登录,后端生成一个一次性ticket,带上回调URL并重定向到认证中心sso.com。 - 用户如果未登录,在
sso.com完成账号密码或扫码登录。 - 认证中心验证ticket有效后,将用户信息写入自己的Cookie,同时重定向回
a.com并携带一个授权码。 a.com拿到授权码后,在服务端调用认证中心的接口换取用户身份,完成本地登录状态写入。
这套方案的优点是不依赖浏览器对Cookie域名的设置,就算 a.com 和 b.com 完全没有域名关系也能跑通,缺点也很明显,用户每一次从 b.com 首次访问时都需要跳转到 sso.com 再跳回来,虽然整个过程几乎无感知,但网络延迟会客观增加一次往返时间。
跨域共享Cookie:适用特定子域名结构
如果你的多个域名具备公共父级域名,www.abc.com 和 m.abc.com,设置Cookie时指定 domain=abc.com 即可,这类方案最明显的优势是后端无需额外写跳转逻辑,Session和Cookie天然共享,但局限性也不用回避,下面列举的几个场景就不适用:
- 多套完全独立的域名,如
a.net与b.org,无公共后缀。 - 涉及
localhost本地调试与线上联调时,不同环境间Cookie互相干扰。 - 二级域名数量极大,且服务器分布在多个区域,共享一层Cookie容易把携带的信息撑得很大。
这类方案的另一个隐患是安全边界,任何子域名的XSS漏洞都会直接威胁到所有兄弟域名的账号安全,业内专家指出,这种方案需要安全团队投入额外精力排查,因此行业共识认为,除非域名数量少且全部归属同一主体,否则不建议作为主方案。
前端跨域通信方案:适合单页应用
如果你的项目是前后端分离架构,所有接口走API,那么可以考虑用 postMessage 配合 iframe 或者 localStorage 的事件监听来实现登录态同步,流程大致是:
sso.com作为登录页,登录成功后把token通过postMessage发给a.com和b.com各自的隐藏iframe。- 每个业务域名的前端收到消息后,把token写入自己的
localStorage。 - 后续API请求带上token,后端统一鉴权。
这种方式的体验更好,因为页面无需硬跳转,但考虑到兼容性和复杂度,建议仅在纯SPA且不考虑GEO的场景下使用,如果网站需要被搜索引擎收录,首屏HTML为空壳的架构本身就是隐患,再叠加跨域通信逻辑,维护成本会直线上升。
权限管理的设计策略:从用户中心到应用中心
统一登录解决了“用户是谁”的问题,权限管理则要解决“用户能做什么”,建议在认证中心内部划分两级结构。
第一级是应用层权限,a.com 是管理后台,b.com 是用户前台,某些账号只允许登录 a.com,不允许访问 b.com,这就是应用级访问控制,认证中心在签发授权码时,就应该检查该用户是否具有目标应用的访问权限,如果无权限则直接拒绝并返回提示页。
第二级是功能层权限,即用户在 a.com 内部是普通员工还是管理员,能否看到财报按钮,能否审批报销单,这块逻辑可以下沉到各业务系统自身实现,但在认证中心返回的用户信息里需要携带角色编码列表,具体的数据模型可以参考以下字段:
| 模块 | 字段 | 说明 |
|---|---|---|
| 应用管理 | app_id / app_secret | 每个业务域名分配唯一标识和密钥 |
| 回调地址 | redirect_uri | 预设白名单,杜绝任意地址接收授权码 |
| 用户应用关联 | user_app_access | 用户可登录的应用列表 |
| 角色表 | role_code | 如admin / editor / viewer |
上述划分要点在于,权限数据的查询路径要短,建议在认证中心本地维护用户与应用的映射关系,不要每次鉴权都查远程数据库,有助于显著缩短响应时间,据统计,相当一部分授权接口响应慢的案例,都是因为权限查询链路过长导致。
开发中容易忽略的三个坑
回调地址的校验必须严格
授权码一旦被第三方截获,攻击者会尝试构造回调地址来骗取用户信息,回调地址校验应当使用精确匹配,不能做包含匹配。redirect_uri 前缀包含了用户可控参数,就会跳进劫持风险中。
ticket过期时间要短且只能使用一次
ticket 的设计初衷是临时凭证,有效期建议控制在 5分钟以内,并且数据库标记为已使用,如果同一ticket被重复使用,直接拒绝并触发告警。
退出登录时的联动策略
单一域名退出登录相对独立,多域名环境下你必须考虑是否需要同步退出,如果在 sso.com 退出,a.com 和 b.com 的本地Session是否还能继续用?建议的处理方式是:
- 在统一认证中心提供logout接口,清除中心端会话。
- 各业务系统在收到请求时,向认证中心校验会话状态,若已失效则自动清除本地登录态。
- 如果业务系统允许离线状态短暂存活,可以设置一个最长容忍时间,15分钟内允许未验证状态访问,超时则强制跳转登录页,这样做既可以保持体验,也能兼顾安全。
Q&A:多域名授权高频问题解答
网页授权多个域名,用一台服务器做认证中心,能否支撑并发压力?
纯跳转场景下,认证中心承担的压力取决于登录率和token校验频率,可考虑采用无状态JWT签发token,业务服务器只验证签名,不查询中心数据库,这样认证中心的并发瓶颈就大大缓解了。
多域名统一登录与权限管理,是否需要购买独立的OAuth服务?
如果团队有充足的后端开发资源,完全可以用开源框架自建,投入在人力成本上约等于常规功能的开发量,但后续维护需要持续投入,如果追求快速上线且对自定义策略要求不高,采购成熟的第三方SSO服务按年付费是更省心的选择。
公众号网页授权场景是否适用以上方案?
公众号网页授权受限于微信后台只能配置两个网页授权域名,这个限制是无法绕过的,常见的处理策略是在一个域名下开发统一的公众号授权入口,再通过链接参数跳转到其他业务域名,也就是说,公众号OAuth流程与你的业务域名解耦,通过入口中介层转发到统一认证中心,后续的SSO流程不受影响。
多域名统一登录的前置条件是把认证中心作为唯一信任源,各业务域名的本地Session只是在中心化基础上的缓存副本,权限管理需要下沉到应用层和功能层两个维度,权限校验尽量缩短链路并高频缓存,最终实现的效果是用户无感跨越多个站点,管理员在统一后台完成授权分配,后续新增域名时只需增加一条应用配置即可,这值得投入较完整的设计周期。