如何處理 Cookie
基於 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
套件)
- 網域
- 編碼
- 到期日
- 僅 HTTP
- 最大年齡
- 路徑
- 同站
- 安全
當擴充至多個節點時(範例與 HAProxy 在此處),此 Cookie 可用於基於 Cookie 的黏著式連線。
應用程式 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 的黏著式連線搭配使用。