跳至主要内容

如何处理 Cookie

当使用 cookie 选项时,服务器将在握手(会话的第一个 HTTP 请求)时发送一个 Cookie,其值为 Engine.IO 会话 ID。

const io = new Server(httpServer, {
cookie: true
});

// is similar to

const io = new Server(httpServer, {
cookie: {
name: "io",
path: "/",
httpOnly: true,
sameSite: "lax"
}
});

您可以使用 curl 进行测试

$ curl "https://mydomain.com/socket.io/?EIO=4&transport=polling" -v
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
< Content-Length: 97
< Set-Cookie: io=G4J3Ci0cNDWd_Fz-AAAC; Path=/; HttpOnly; SameSite=Lax
<
0{"sid":"G4J3Ci0cNDWd_Fz-AAAC","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":20000}

可用选项(来自 cookie 包)

  • 编码
  • 过期时间
  • httpOnly
  • maxAge
  • 路径
  • sameSite
  • 安全

此 Cookie 随后可用于基于 Cookie 的粘性会话,在扩展到多个节点时(HAProxy 示例 在此)。

应用程序 Cookie

您还可以自定义服务器发送的标头

import { serialize, parse } from "cookie";

// called during the handshake
io.engine.on("initial_headers", (headers, request) => {
headers["set-cookie"] = serialize("uid", "1234", { sameSite: "strict" });
});

// called for each HTTP request (including the WebSocket upgrade)
io.engine.on("headers", (headers, request) => {
if (!request.headers.cookie) return;
const cookies = parse(request.headers.cookie);
if (!cookies.randomId) {
headers["set-cookie"] = serialize("randomId", "abc", { maxAge: 86400 });
}
});
注意

请注意,事件发射器是同步的

io.engine.on("initial_headers", async (headers, request) => {
// WARNING! this won't work
const session = await fetchSession(request);
headers["set-cookie"] = serialize("sid", session.id, { sameSite: "strict" });
});

如果您需要执行一些异步操作,则需要使用 allowRequest 选项。

请查看 此示例,其中包含 express-session 的参考。

Node.js 客户端和 Cookie

从版本 4.7.0 开始,当将 withCredentials 选项设置为 true 时,Node.js 客户端现在将在 HTTP 请求中包含 Cookie,使其更易于与基于 Cookie 的粘性会话一起使用。