如何处理 cookies
¥How to deal with cookies
基于 Cookie 的粘性会话
¥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 });
}
});
请注意,事件触发器是同步的:
¥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.