0
  • 我有一个简单的演示设置,其中包含 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"));
4

0 回答 0