- 我有一个简单的演示设置,其中包含 3 条路由:登录、注销和 GET 用户
- 当用户使用本地护照登录时,我可以检索他们的会话数据。
- 我正在将 ws 用于 websockets,我希望在 websocket 服务器的升级事件中登录用户的 id
如何在下面的代码示例中检索它?
/**
* Simple Idea to recreate the problem
* 1) Define a passport serialize, deserialize with local strategy that takes a simple hardcoded username and password
* 2) Do a GET request to user endpoint, you should get undefined
* 3) Do a POST request to login endpoint with "email": "test@example.com" and "password":"123456789", it will be successful
* 4) Open a websocket request to ws://localhost:3000 and send an {"event": "message"}
* Problem is req.user is undefined inside the websocket parser! how to fix this?
*/
const http = require("http");
const express = require("express");
const passport = require("passport");
const cookieSession = require("cookie-session");
const { Strategy: LocalStrategy } = require("passport-local");
const { Server } = require("ws");
const loggedInUser = {
userId: 1,
userName: "test@example.com",
isAdmin: false,
};
const sessionParser = cookieSession({
name: "test",
secret: "abracadabra",
// Cookie Options
maxAge: 1000 * 5 * 60, // 24 hours
sameSite: false,
secure: false,
httpOnly: false,
});
const app = new express();
// Add passport, serialize, deserialize and local strategy with hardcoded username and password
passport.serializeUser((user, done) => {
done(null, user.userId);
});
passport.deserializeUser(async (userId, done) => {
done(null, loggedInUser);
});
passport.use(
"local",
new LocalStrategy(
{
usernameField: "email",
passwordField: "password",
badRequestMessage: "email or password is missing",
},
async (email, password, done) => {
if (email === "test@example.com" && password === "123456789") {
return done(null, loggedInUser);
} else {
return done(null, false);
}
}
)
);
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(sessionParser);
app.use(passport.initialize());
app.use(passport.session());
// Retrieve user after login
app.get("/user", (req, res) => {
console.log(req.session.passport.user, 'I can retrieve the user here');
return res.json(req.user);
});
app.post("/login", (req, res, next) => {
passport.authenticate("local", {}, async (error, user, info) => {
if (error) {
return next(error);
}
if (!user) {
return res.json(false);
}
req.logIn(user, (error) => {
if (error) {
return next(error);
}
return res.json(user);
});
})(req, res, next);
});
app.post("/logout", (req, res, next) => {
req.logout();
req.session = null;
req.user = null;
res.clearCookie(`test.session`, {});
res.clearCookie(`test.session.sig`, {});
return res.json(true);
});
const map = new Map();
const server = http.createServer(app);
const websocketServer = new Server({ noServer: true });
server.on("upgrade", (request, socket, head) => {
sessionParser(request, {}, () => {
console.log("How to get the user id here?", request.headers.cookie, request.session.user, request.user);
websocketServer.handleUpgrade(request, socket, head, function (ws) {
websocketServer.emit("connection", ws, request);
});
});
});
websocketServer.on("connection", function (ws, request) {
const user = request.session.user;
map.set(user, ws);
ws.on("message", function (message) {
//
// Here we can now use session parameters.
//
console.log(`Received message ${message} from user ${user}`);
});
ws.on("close", function () {
map.delete(user);
});
});
server.listen(3000, () => console.log("server listening on 3000"));