解释“_session” Cookie 的“SameSite=Lax”在跨域同步时的影响。
解读
在国内生产环境中,CouchDB 常被用作移动端离线数据的中转节点,客户端通过 HTTP/REST 完成登录后,服务端会在响应头里种下名为 _session 的认证 Cookie。
该 Cookie 的 SameSite=Lax 属性由 Erlang/OTP 的 cowboy 默认写入,它告诉浏览器“只允许同站或顶级导航时携带此 Cookie”。
当业务出现“跨域同步”场景——典型如 H5 页面域名 a.example.com 需要把本地 PouchDB 数据同步到 CouchDB 域名 b.example.com——浏览器会首先发一条 GET /_session 请求确认登录态。
此时若协议、域名或端口任一不同,浏览器判定为跨站,于是不会在请求头里带上 SameSite=Lax 的 Cookie;CouchDB 收到无 Cookie 的请求后返回 401,触发登录重定向,同步流程被中断。
结果表现为:
- 用户已在 b.example.com 登录,但在 a.example.com 点击“同步”仍提示“未授权”;
- 开发者工具 Network 面板可见 _session 请求无 Cookie,响应 401;
- 国内主流浏览器(Chrome、Edge、360 极速、QQ、UC)在 2021 年后全部默认启用 SameSite=Lax,因此问题必现,与“是否关闭第三方 Cookie”无关。
知识点
- SameSite 三取值:Strict 完全禁止跨站发送;Lax 允许顶级导航 GET;None 必须搭配 Secure。
- CouchDB 的 Cookie 写入口:
couch_httpd_auth模块,配置项same_site=lax可改。 - 跨域同步的两种形态:
- CORS 直接同步:前端 Ajax 访问远端 CouchDB,受 SameSite 限制;
- 反向代理收敛域名:通过 nginx 把
/_session与/_replicate代理到同站,规避浏览器限制。
- 国内移动端特例:微信、钉钉内置 WebView 同样遵循 Chromium SameSite 规则,不存在“白名单”。
- 合规风险:把 SameSite 改成 None 时必须开启 HTTPS,否则浏览器直接拒绝写入,满足等保 2.0 传输加密要求。
答案
“_session” Cookie 的 SameSite=Lax 会在跨域同步时导致浏览器不发送该 Cookie,使 CouchDB 认为请求未认证,返回 401,从而阻断同步。
解决思路:
- 同站化:让页面与 CouchDB 处于同一站点(子域名共享根域,或 nginx 反向代理到同域)。
- 修改 SameSite:在
local.ini中设置
并强制全站 HTTPS,确保 Cookie 被浏览器接受。[httpd] same_site = none [ssl] enable = true - Token 替代方案:放弃 Cookie,改用 JWT 或 Basic Auth+_session 一次性令牌,在每次同步请求头里手动携带 Authorization,绕过 Cookie 策略。
拓展思考
- 如果企业内网仍使用 HTTP,SameSite=None 会被浏览器拒绝,此时只能采用同站代理或 Token 方案,无法依赖 Cookie。
- 在国内小程序生态里,Web-view 组件对 SameSite 的处理与系统浏览器一致,但小程序网络接口 wx.request 不受 Cookie 限制,可把同步逻辑挪到原生层规避该问题。
- 多租户 SaaS 场景下,每个租户分配独立子域(tenant-id.saas.cn),CouchDB 统一在
db.saas.cn,此时根域不同,即使反向代理也需解决证书 wildcard 成本,Token 方案反而更轻量。 - 未来 Chrome 将逐步取消第三方 Cookie,但 SameSite 对“第一方”定义以可注册域为准,因此把页面和 API 放在同一根域下的子域方案仍长期有效,是国内金融、政务云落地时的首选架构。