ExpressJS & Websocket & session sharing

后端 未结 5 1352
情书的邮戳
情书的邮戳 2020-12-01 09:30

I\'m trying to make a chat application based on Node.js. I\'d like to force websocket server (ws library) to using ExpressJS session system. Unfortunately, I\'ve got stuck.

相关标签:
5条回答
  • 2020-12-01 09:48

    I found this works for me. Not sure it's the best way to do this though. First, initialize your express application:

    // whatever your express app is using here...
    var session = require("express-session");
    var sessionParser = session({
        store: session_store,
        cookie: {secure: true, maxAge: null, httpOnly: true}
    });
    app.use(sessionParser);
    

    Now, explicitly call the session middleware from the WS connection. If you're using the express-session module, the middleware will parse the cookies by itself. Otherwise, you might need to send it through your cookie-parsing middleware first.

    If you're using the websocket module:

    ws.on("request", function(req){
        sessionParser(req.httpRequest, {}, function(){
            console.log(req.httpRequest.session);
            // do stuff with the session here
        });
    });
    

    If you're using the ws module:

    ws.on("connection", function(req){
        sessionParser(req.upgradeReq, {}, function(){
            console.log(req.upgradeReq.session);
            // do stuff with the session here
        });
    });
    

    For your convenience, here is a fully working example, using express, express-session, and ws:

    var app = require('express')();
    var server = require("http").createServer(app);
    var sessionParser = require('express-session')({
        secret:"secret",
        resave: true,
        saveUninitialized: true
    });
    app.use(sessionParser);
    
    app.get("*", function(req, res, next) {
        req.session.working = "yes!";
        res.send("<script>var ws = new WebSocket('ws://localhost:3000');</script>");
    });
    
    var ws = new require("ws").Server({server: server});
    ws.on("connection", function connection(req) {
        sessionParser(req.upgradeReq, {}, function(){
            console.log("New websocket connection:");
            var sess = req.upgradeReq.session;
            console.log("working = " + sess.working);
        });
    });
    
    server.listen(3000);
    
    0 讨论(0)
  • 2020-12-01 09:59

    In version 3.2.0 of ws you have to do it a bit differently.

    There is a full working example of express session parsing in the ws repo, specifically using a new feature verifyClient.

    A very brief usage summary:

    const sessionParser = session({
      saveUninitialized: false,
      secret: '$eCuRiTy',
      resave: false
    })
    
    const server = http.createServer(app)
    const wss = new WebSocket.Server({
      verifyClient: (info, done) => {
        console.log('Parsing session from request...')
        sessionParser(info.req, {}, () => {
          console.log('Session is parsed!')
          done(info.req.session.userId)
        })
      },
      server
    })
    
    wss.on('connection', (ws, req) => {
      ws.on('message', (message) => {
        console.log(`WS message ${message} from user ${req.session.userId}`)
      })
    })
    
    0 讨论(0)
  • 2020-12-01 10:03

    I was able to get this working. I think you need to specify the secret on cookieParser instead of session store.

    Example from my app:

    var app = express();
    var RedisStore = require('connect-redis')(express);
    var sessionStore = new RedisStore();
    var cookieParser = express.cookieParser('some secret');
    
    app.use(cookieParser);
    app.use(express.session({store: sessionStore}));
    
    
    wss.on('connection', function(rawSocket) {
    
      cookieParser(rawSocket.upgradeReq, null, function(err) {
        var sessionID = rawSocket.upgradeReq.signedCookies['connect.sid'];
        sessionStore.get(sessionID, function(err, sess) {
          console.log(sess);
        });
      });
    
    });
    
    0 讨论(0)
  • 2020-12-01 10:06

    WS v3.0.0 and above, has changed the behaviour so the given answers won't work out of the box for those versions. For current versions, the signature of the connection method is [function(socket, request)] and the socket no longer contains a reference to the request.

    ws.on(
        'connection',
        function (socket, req)
        {
            sessionParser(
                req,
                {},
                function()
                {
                    console.log(req.session);
                }
            );
        }
    );
    
    0 讨论(0)
  • 2020-12-01 10:09

    Currently, below is my workaround which is working fine. I just don't know it's disadvantages and security. I just prevent the server from listening if it doesn't have a session. (Share session from express-session to ws)

    I haven't fully tested this though.

    var http = require('http');
    var express = require('express');
    var expressSession = require('express-session');
    var router = express.Router();
    var app = express();
    
    const server = http.createServer(app);
    
    router.get('/', function(req, res, next) {
        if(req.session.user_id) {
            // Socket authenticated
            server.listen(8080, function listening(){});
        }
    });
    
    0 讨论(0)
提交回复
热议问题