简体   繁体   中英

[Express][Nodejs] How to decrypt express-session cookie during socket.io connection?

After successful login, userId and Name of the user are saved in a cookie.

server.js

const io = require('socket.io')(http)
const session = require('express-session')


const Allusers = [ {id: 1, name: 'Admin', username: 'admin', password: 'admin'} ]
const socketName = {}

app.use(session({
    name: 'sid',
    resave: false,
    saveUninitialized: false,
    secret: 'secretCode!',

    cookie: {
        httpOnly: false,    
        maxAge: 1000 * 60 * 60 * 24 * 30, // 1  month
        sameSite: true
    }
}))


// FOR USER LOGIN AND SAVING COOKIE
app.post('/login', (req,res) =>{

    const {username, password} = req.body

    if (username && password){

        const user = Allusers.find(user => user.username === username && user.password === password)
        if (user){
            req.session.userId = user.id
            req.session.name = user.name
            return res.redirect('/')
        }

    }
    res.redirect('/login')
})





io.on('connection', (socket) => {

    //   I WANT TO GET NAME AND ID OF THE USER FROM COOKIE, THEN ADD THEM TO socketName as
    //   {'socket_id' : 'Name of the user'}

});

I want to get name and id of the user from cookie, then add them to socketname as

{'socket_id': 'Name of the user'}

I'm able to get cookie using socket.handshake.headers.cookie , but it is encrypted using the secret string.

How can I decrypt cookie data or verify the user from Allusers ?

For your case, first of all, you need to know that the session id is generated by a generating function - generateSessionId (by default). This means the session id( sid cookie) DOES NOT contain any user data, the user data stored on the server-side( MemoryStore by default). So you should get the user session data from the server-side rather than get them from the sid cookie.

The operations like:

req.session.userId = userId;
req.session.name = name;

The userId and name will be stored in MemoryStore on the server-side.

Now, let's get the session data. The value of socket.request.headers.cookie will be a string like this:

sid=s%3AfWB6_hhm39Z7gDKvAYFjwP885iR2NgIY.uT80CXyOKU%2Fa%2FxVSt4MnqylJJ2LAFb%2B770BItu%2FpFxk; io=msngndIn0v4pYk7DAAAU
  1. we should use cookie.parse(str, options) method to parse string to a JavaScript plain object.
{
  sid: 's:fWB6_hhm39Z7gDKvAYFjwP885iR2NgIY.uT80CXyOKU/a/xVSt4MnqylJJ2LAFb+770BItu/pFxk',
  io: 'eeOnxhDIiPSE_0gfAAAm'
}
  1. We should unsign the signed cookie use cookieParser.signedCookie(str, secret) method. Get the unsigned sid :
fWB6_hhm39Z7gDKvAYFjwP885iR2NgIY
  1. Since the default server-side session storage is MemoryStore , you need to initialize it explicitly and call store.get(sid, callback) in the WebSocket connection callback function to get the user session data by sid .

The complete working example:

const session = require('express-session');
const app = require('express')();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const cookie = require('cookie');

const Allusers = [{ id: 1, name: 'Admin', username: 'admin', password: 'admin' }];
const MemoryStore = new session.MemoryStore();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(
  session({
    store: MemoryStore,
    name: 'sid',
    resave: false,
    saveUninitialized: false,
    secret: 'secretCode!',

    cookie: {
      httpOnly: false,
      maxAge: 1000 * 60 * 60 * 24 * 30,
      sameSite: true,
    },
  }),
);

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});

app.post('/login', (req, res) => {
  const { username, password } = req.body;
  console.log(username, password);
  if (username && password) {
    const user = Allusers.find((user) => user.username === username && user.password === password);
    console.log(user);
    if (user) {
      req.session.userId = user.id;
      req.session.name = user.name;
      return res.redirect('/');
    }
  }
  res.redirect('/login');
});

io.on('connection', (socket) => {
  console.log('a user connected');
  const cookieString = socket.request.headers.cookie;
  console.log('cookieString:', cookieString);
  if (cookieString) {
    const cookieParsed = cookie.parse(cookieString);
    console.log('cookieParsed:', cookieParsed);
    if (cookieParsed.sid) {
      const sidParsed = cookieParser.signedCookie(cookieParsed.sid, 'secretCode!');
      console.log(sidParsed);
      MemoryStore.get(sidParsed, (err, session) => {
        if (err) throw err;
        console.log('user session data:', JSON.stringify(session));
        const { userId, name } = session;
        console.log('userId: ', userId);
        console.log('name: ', name);
      });
    }
  }
});

http.listen(3000, () => {
  console.log('listening on *:3000');
});

You will get the session data userId and name like this:

user session data: {"cookie":{"originalMaxAge":2592000000,"expires":"2021-02-14T08:31:50.959Z","httpOnly":false,"path":"/","sameSite":true},"userId":1,"name":"Admin"}
userId:  1
name:  Admin

source code: https://github.com/mrdulin/expressjs-research/tree/master/src/stackoverflow/62407074

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM