页面被别的站点嵌进去时,登录凭据按顶层站点分区是怎么回事
页面被别的站点嵌进去时,登录凭据按顶层站点分区,意思是同一份凭据不再全局共用一份数据,而是按「谁在顶层」分开存。直接访问站点时读到的是以本站为顶层的那一份;页面被嵌进别人的站点时,读写的是以那个站点为顶层划分出来的另一份。分区机制解决的是跨站跟踪,代价正是嵌入方再也共享不到主站的登录态。
分区把同一份凭据拆成了什么
不分区时,凭据按站点自身归属存储,无论从哪里发起请求都是同一份。加上分区属性后,存储键变成顶层站点与自身站点的组合:顶层是 A 时是一份,顶层是 B 时是另一份,直接访问时又是一份。按官方文档的措辞,这个属性表示该凭据应使用分区存储。它没有增加或删除任何一份数据的权限,只是改变了它们之间的隔离关系。
为什么必须同时带安全标记
文档里两处重复强调:设置了分区属性就必须同时设置安全标记,分区凭据必须以安全方式传输。原因是分区设计的前提是加密通道——它要控制的是不同上下文里凭据被带出去的时机,若凭据可以在明文连接上被传输,隔离就失去意义。除了安全标记,文档还建议用带主机名的前缀命名,让凭据绑定到具体主机而不是可注册域,避免同域下另一个子域误读到它。一条完整写法要同时出现四项:跨站发送、安全标记、路径限定与分区属性。
嵌入页面读不到的三种典型表现
第一种是登录态丢失:页面被嵌进合作方站点后需要登录的地方一律显示未登录,因为分区后读到的是以对方站点为顶层的那一份,通常是空的。第二种是状态不一致:同一地址在直接访问时是登录状态,在嵌入环境下却把操作跳到登录页,两边写入了不同的数据。第三种是 CSRF 防护与状态校验报错:请求带着某一份凭据发出,校验却按另一份上下文来做。这三种表现的共同点在于,问题只在嵌入环境出现,本地直接访问复现不了。
改造前先确认的两件事
第一件事是这份凭据到底该不该被共享。登录凭据的常见设计目标是「在我自己的站点上是谁」,一旦把它交给分区机制,等于承认在不同顶层环境下它是不同的身份。AnQiCMS 的认证走 JWT,登录凭证的传递与后台权限校验按自身站点判断,用户管理和 VIP 分组决定不同用户组能读到哪些内容——这套设计本身就假设身份归属与站点绑定,而不是与嵌入口吻绑定。第二件事是嵌进去的那块页面究竟需不需要登录态。多数展示型嵌入不需要,让它读不到反而是正确行为;确实需要时,正确的解法不是取消分区,而是改成由顶层页面携带一次性凭据跳转,或者用接口在服务端之间取数据。
| 场景 | 分区后的表现 | 是否算问题 | 处理方向 |
|---|---|---|---|
| 直接访问站点 | 读到以本站为顶层的那份数据 | 正常 | 无需改动 |
| 被别的站点嵌入展示 | 读到以对方为顶层的另一份,通常为空 | 正常 | 保持只读展示,不要求登录 |
| 嵌入页面要执行写操作 | 校验按另一份上下文进行,容易失败 | 是 | 改为跳转回本站完成 |
| 希望跨上下文共享同一份数据 | 分区机制天然做不到 | 是 | 用服务端接口换数据,别放开分区 |
常见问题
问:去掉分区属性是不是就能让嵌入页面读到登录态? 答:技术上可以,代价是放弃这层隔离,让同一份凭据跨顶层上下文被带上,与浏览器收紧跟踪的目的相反。
问:分区和跨站标记是什么关系? 答:两件事。跨站标记决定这份数据能不能在跨站请求中被发送,分区决定发送时读到的是哪一份存储。
问:为什么建议用带主机名的前缀? 答:为了让凭据绑定到具体主机而非可注册域,避免同域下的其他主机读到它。