Skip to main content

如何处理 cookies

¥How to deal with cookies

¥Cookie-based sticky session

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

¥When using the cookie option, the server will send a cookie upon handshake (the first HTTP request of the session), with the value of the Engine.IO session 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 进行测试:

¥You can test it with a 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 软件包):

¥Available options (from the cookie package):

  • 字段

    ¥domain

  • 编码

    ¥encode

  • 过期

    ¥expires

  • 仅 http

    ¥httpOnly

  • 最大年龄

    ¥maxAge

  • 路径

    ¥path

  • 同一站点

    ¥sameSite

  • 安全的

    ¥secure

当扩展到多个节点时(例如使用 HAProxy 此处),此 cookie 可用于基于 cookie 的粘性会话。

¥This cookie can then be used for cookie-based sticky session, when scaling to multiple nodes (example with HAProxy here).

应用 cookies

¥Application cookies

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

¥You can also customize the headers sent by the server:

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 });
}
});
caution

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

¥Please note that event emitters are synchronous:

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 选项。

¥If you need to do some async operations, you will need to use the allowRequest option.

请检查 这个例子express-session 以供参考。

¥Please check this example with express-session for reference.

Node.js 客户端和 cookie

¥Node.js client and cookies

从版本 4.7.0 开始,当将 withCredentials 选项设置为 true 时,Node.js 客户端现在将在 HTTP 请求中包含 cookie,从而更轻松地在基于 cookie 的粘性会话中使用它。

¥Starting with version 4.7.0, when setting the withCredentials option to true, the Node.js client will now include the cookies in the HTTP requests, making it easier to use it with cookie-based sticky sessions.