node.js - [Express][Nodejs] 如何在 socket.io 连接期间解密 express-session cookie?

标签 node.js express cookies socket.io express-session

登录成功后,用户的userId和Name保存在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'}

});

我想从 cookie 中获取用户的 nameid,然后将它们添加到 socketname 作为

{'socket_id' : '用户名'}

我可以使用 socket.handshake.headers.cookie 获取 cookie,但它是使用 secret 字符串加密的。

如何从 Allusers 解密 cookie 数据或验证用户?

最佳答案

对于您的情况,首先,您需要知道 session ID 是由生成函数生成的 - generateSessionId (默认)。这意味着 session id(sid cookie) 不包含任何用户数据,用户数据存储在服务器端(默认情况下为 MemoryStore)。因此,您应该从服务器端获取用户 session 数据,而不是从 sid cookie 中获取它们。

操作如:

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

userIdname 将存储在服务器端的MemoryStore 中。

现在,让我们获取 session 数据。 socket.request.headers.cookie 的值将是这样的字符串:

sid=s%3AfWB6_hhm39Z7gDKvAYFjwP885iR2NgIY.uT80CXyOKU%2Fa%2FxVSt4MnqylJJ2LAFb%2B770BItu%2FpFxk; io=msngndIn0v4pYk7DAAAU
  1. 我们应该使用cookie.parse(str, options)将字符串解析为 JavaScript 普通对象的方法。
{
  sid: 's:fWB6_hhm39Z7gDKvAYFjwP885iR2NgIY.uT80CXyOKU/a/xVSt4MnqylJJ2LAFb+770BItu/pFxk',
  io: 'eeOnxhDIiPSE_0gfAAAm'
}
  1. 我们应该取消签署已签名的 cookie 使用 cookieParser.signedCookie(str, secret)方法。获取未签名的 sid:
fWB6_hhm39Z7gDKvAYFjwP885iR2NgIY
  1. 由于默认的服务器端 session 存储是MemoryStore,您需要对其进行显式初始化并调用store.get(sid, callback)。在WebSocket连接回调函数中通过sid获取用户 session 数据。

完整的工作示例:

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');
});

您将像这样获取 session 数据userIdname:

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

源代码:https://github.com/mrdulin/expressjs-research/tree/master/src/stackoverflow/62407074

关于node.js - [Express][Nodejs] 如何在 socket.io 连接期间解密 express-session cookie?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62407074/

相关文章:

json - npm 安装错误 - 无效的 package.json

go - net/http auth 方法不稳定

php - 如何在 php 中发送 cookie 值的正确翻译

Javascript国际象棋符号转换函数

node.js - gulp 命令给出模块错误找不到

node.js - `Extensions` 字段未显示在 apollo graphql 响应数据中

node.js - 尝试将 LowDB 与现有 db.json 集成

javascript - Firebase 托管 : how to generate a global 'map/array' that can be used on all pages instead of parsing the database on each page load

node.js - 在nodejs中模拟电子邮件功能

asp.net - 渗透测试人员说 .ASPXAUTH cookie 不安全并且正在显示 session 数据?