Encore.ts 能否在认证网关中直接清除过期会话的 Cookie?
结论
不能直接通过 Encore.ts 的 authHandler 清除浏览器 Cookie。它负责返回认证数据或抛出认证错误,不提供用于修改客户端 HTTP 响应的响应对象。清理 Cookie 应放在能够返回响应的 API endpoint 或 middleware 中。
对于设置了 auth: true 的接口,认证失败后,客户端可以调用一个无需认证的清理接口,让该接口通过响应使 Cookie 立即过期。
为什么抛出认证错误还不够?
服务端判定 session token 过期后,浏览器保存的 Cookie 不会自动删除。浏览器仍会按照 Cookie 自身的有效期继续发送它。
Encore 的认证流程也会影响清理代码能否执行:
- auth handler 抛出
APIError.unauthenticated(...)时,请求被视为未认证。 - 目标接口要求
auth: true时,网关会直接拒绝请求,不会进入目标接口及其服务 middleware。 - 目标接口不要求认证时,请求仍可继续执行。
- auth handler 抛出其他异常时,即使目标接口不要求认证,网关也会中止请求。
因此,即使清理接口无需认证,auth handler 也应在 token 过期时抛出 APIError.unauthenticated(...),以免其他异常使网关提前中止请求。参见 Encore 认证流程文档。
实现一个不要求认证的 Cookie 清理接口
下面的示例假设 Cookie 名称为 session,创建时使用 Path=/,未设置 Domain,并通过 HTTPS 访问。实际使用时,应替换为应用中的名称和作用域。
import { api, Cookie } from "encore.dev/api";
interface ClearSessionResponse {
session: Cookie<"session">;
}
export const clearSession = api(
{
expose: true,
auth: false,
method: "POST",
path: "/auth/clear-session",
},
async (): Promise<ClearSessionResponse> => {
return {
session: {
value: "",
path: "/",
maxAge: 0,
httpOnly: true,
secure: true,
sameSite: "Lax",
},
};
},
);
Encore 支持在 API 响应类型中使用 Cookie<"名称">,并配置 maxAge、path、domain 等属性。上面的接口通过响应 Cookie 发出删除指令。参见 Encore Cookie 文档。
客户端确认会话无效后调用该接口。同源部署时,例如可以使用:
const response = await fetch("/auth/clear-session", {
method: "POST",
credentials: "include",
});
if (!response.ok) {
throw new Error("Failed to clear session cookie");
}
建议将调用放在统一的会话失效处理逻辑中,避免多个失败请求反复触发清理。如果已有 session refresh 流程,应先确定刷新失败,再清理会话并引导用户重新登录。
可以通过 middleware 自动清理吗?
可以,但请求必须能够到达服务。对于允许匿名访问的接口,middleware 可以在 await next(req) 后检查 getAuthData(),并通过 resp.header.add("Set-Cookie", ...) 添加删除 Cookie 的响应头。middleware 需要注册到对应的 Service。
这种方法无法覆盖已被网关拒绝的 auth: true 请求。另外,getAuthData() === null 只表示没有认证数据,无法单独证明 token 已过期。不要把清理逻辑无条件应用到所有匿名接口,尤其要避免覆盖登录接口刚设置的新 Cookie。相关响应头 API 见 Encore middleware 文档。
Cookie 仍未删除时检查什么?
删除 Cookie 时,需要返回同名 Cookie,匹配原来的 Path 和 Domain,并设置 Max-Age=0 或过去的 Expires。仅将值设为空字符串不会删除 Cookie。HttpOnly Cookie 也需要由服务端响应清理,页面脚本无法通过 document.cookie 修改它。参见 MDN Cookie 文档。
还应检查以下条件:
- 示例中的
secure: true面向 HTTPS;本地 HTTP 调试时需按实际环境调整。 - 跨域调用需要携带 credentials,并配置允许凭据的 CORS;跨站请求还会受到
SameSite和浏览器 Cookie 策略限制。 - 在浏览器开发者工具中确认清理响应包含
Set-Cookie,并检查后续请求是否仍携带旧 Cookie。 - 如果清理接口同时承担完整退出登录功能,还应按会话存储方式撤销服务端 session;删除浏览器 Cookie 只处理客户端状态。
备注:内容仅供参考。
