DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

Caddy forward_auth 刷新了会话,浏览器却没收到 Set-Cookie

鉴权子请求返回的刷新Cookie未到浏览器时,区分copy_headers请求方向与响应头复制,保留有序鉴权、全部Set-Cookie及身份头防伪。

认证服务已经给鉴权请求返回了新的 Set-Cookie,浏览器下一次访问却仍带着旧会话,导致每个请求都重复刷新。先核对这条头出现在哪个响应里:认证服务的 2xx 子响应,与应用最终发给浏览器的响应,是两个不同的响应。

Caddy 的 forward_auth 在鉴权成功后继续处理原请求。copy_headers 把认证响应中的指定头复制到原请求,供后面的应用读取;把 Set-Cookie 加进这个列表,不会让浏览器更新 Cookie。本文处理已经确认认证成功、刷新头停留在子响应的情况;浏览器已经收到头却拒绝存储,应另查公开域名、Path 和安全属性。

沿着一次刷新检查两个响应

用测试账户触发已知的刷新条件,分别检查认证端点的成功响应,以及同一次访问最终返回给浏览器的响应。记录状态、Cookie 名称和属性,遮盖值;不要为了诊断把所有用户的会话内容写进访问日志。

如果认证端点没有发出刷新头,应先处理认证服务的刷新契约。只有子响应含有它、最终响应缺少它,才进入这里的复制方案。最终响应已经包含同名 Cookie 时,还要检查应用是否另加或覆盖了 Cookie,不能只确认某一层出现过一个头。

一次刷新可能设置多个 Cookie。它们需要保持各自独立的 Set-Cookie 字段,不能用逗号合并,也不要只取一个头值便认定全部复制完成。

在鉴权成功分支复制响应头

按 Caddy 2.11.7 的正式处理路径,可用展开的鉴权 reverse_proxy 在 2xx 分支中执行 copy_response_headers。下面仅展示需加入已有成功分支的部分:

@authenticated status 2xx
handle_response @authenticated {
    copy_response_headers {
        include Set-Cookie
    }
}

这不是完整站点配置。它必须位于执行鉴权请求的 reverse_proxy 内,合入原有成功分支,保留该分支其他逻辑。不能拿它替换整个认证或应用代理块,也不能在 forward_auth 简写内另塞一个竞争同样 2xx 的处理器:简写本来就会生成成功响应处理,第一条匹配分支的顺序需要核对。

展开形式仍应以 GET 调用正确的认证 URI,保留原始请求方法和 URI 的传递,以及原请求体供应用使用。用 route 保证鉴权代理先执行、应用代理后执行;非 2xx 的拒绝与登录跳转仍返回客户端,不能让它们继续进入应用。成功分支复制头后不直接写出认证响应体,后面的应用才有机会返回原请求的业务响应。

若应用还依赖认证端点返回的身份头,保留这部分可信复制逻辑。先清除客户端能预先提交的相应身份头,再根据认证服务实际返回值设置,尤其要处理认证响应缺少该字段的情况;不能沿用客户端伪造值,也不能把未替换的占位符当成身份。复制 Cookie 响应头不会替代身份验证。

头被复制出来后,浏览器看到的是应用的公开响应地址。认证服务若返回只适用于认证域名的 Domain,转到应用响应里仍可能被浏览器拒绝;内部代理地址正确并不足以证明属性正确。

由认证服务按部署契约生成适用于公开响应的 Domain、Path、Secure、HttpOnly 和 SameSite,保留原安全要求。不要为了存储成功就扩大到父域或删除安全属性。若刷新依赖特定认证产品的回调与会话设计,先核对其公开 base URL、回调和会话范围。

加载后再检查下一次请求

先备份目标配置,在本机用与实例一致的 Caddy 版本适配并验证,检查生成配置中鉴权和应用的先后顺序。按原部署流程加载后,重新触发测试会话刷新,确认最终响应携带全部预期 Cookie,浏览器接受它们,下一次请求带回新值且不再重复刷新。

同时检查匿名访问、失效会话、登录跳转,以及客户端伪造身份头不能进入受保护业务。只验证登录成功一条路径,无法排除展开配置时遗漏拒绝分支。

出现异常时恢复本次鉴权配置;服务器回退不会自动撤回浏览器已经存储的 Cookie。仅对测试账户核对相关 Cookie 和认证状态,保留必要诊断,再用原流程检查回退后的登录与退出。