内嵌 WebView 登录一夜全挂,先查 SameSite 是不是被改严了?

用户反馈说 App 里登录页一直转圈,桌面浏览器打开同一套页面却正常。服务端日志里有的能看到回调打进来,有的连会话 Cookie 都没带上。这类「WebView 里突然全挂、外置浏览器没事」的事故,排的时候很容易先怪客户端壳。真正先对一下的,往往是响应头里的 SameSite。

三个取值各自管什么

web.dev《SameSite cookies explained》 一文把 SameSite 说成三种声明:

  • Strict:基本只在第一方、地址栏就是你这个站的时候带上。从外站点进你站的首次导航,也不带这枚 Cookie。适合改密码、下单确认这类「进站以后再动手」的动作。
  • Lax:同站请求会带。从外站点进你站的顶层导航也会带。嵌在别人页面里的图片、iframe 请求仍不带。展示类偏好、一般登录态,很多站点会落在这一档。
  • None:跨站上下文也想带上时用。文章写明,SameSite=None 必须同时带 Secure,也就是只在安全上下文里发,否则浏览器可以直接拒收。

文里还提到:不写 SameSite 时,新行为会把 Cookie 当成 Lax 来对待。仍建议显式写出 SameSite=Lax,减少各家默认值不一致带来的落差。跨站小部件、嵌入式登录、多站点共用会话,才需要认真评估 None; Secure。

WebView 场景里为什么特别容易炸

App 内 WebView 套的是某代浏览器内核。内核一升级,默认 Cookie 策略、分区存储、第三方 Cookie 限制都可能跟着变。登录若走过「主站 → 认证域 → 再跳回」这种跨站点链路,原先能带上的 Cookie 在更严的默认下会安静消失,页面只剩转圈或立刻被踢回登录页。

桌面浏览器正常、WebView 失败,并不自动证明是 SameSite,但足以把「跨站有没有带上会话」提到检查清单前几位。反过来,桌面也能复现,就先别只盯壳,服务端 Set-Cookie 和回调域更该先看。

可以按这个顺序排

  • 同一账号在系统浏览器里走一遍完整登录,能不能复现。
  • 登录跳转有没有跨站:看地址栏主机是不是换到了另一站点(公后缀规则下的「站」),而不是只盯子域。
  • 响应里会话 Cookie 的 SameSite 写成了什么。若是 None,有没有漏 Secure。
  • 落没落在第三方 / 嵌入上下文:WebView 里加载的页面、中间页、回调页,各自算第一方还是第三方。
  • 客户端或系统 WebView 版本最近有没有升级。对照发行说明里 Cookie、跟踪防护、分区存储相关条目。只读发行说明和自己的响应头,别想着去绕过用户的跟踪防护设置。

改服务端 Set-Cookie 之前,先在测试环境用两三种 WebView / 浏览器版本对着 Network 面板看请求有没有带上那枚 Cookie。缺 Secure 的 None、该跨站却写成 Strict、默认变 Lax 后嵌入场景不再带 Cookie,这几类都能在头字段里对上号。

登录态要跨站点携带的话,按 web.dev 的口径应显式 SameSite=None; Secure,并确认整条链路都是 HTTPS。若业务其实只在顶层跳转回站,Lax 往往就够,盲目改成 None 只会扩大 Cookie 的跨站暴露面。排查停在「对一下头、对一下版本、对一下跨不跨站」,不要把用户的跟踪防护、智能防跟踪开关当成「障碍」去教人关掉。

和 CORS 带凭证是另一条线:CORS 过了仍可能因为 SameSite 不带 Cookie。两件事一起炸的时候,先分清失败发生在预检/响应头,还是发生在 Cookie 根本没附上。

有没有人碰上过「只有某种机型的 WebView 挂、同版本桌面内核却正常」?最后是改头字段解决的,还是客户端升级连带好的?