Node.js [Express][Nodejs]如何在socket.io连接期间解密Express会话cookie?

Node.js [Express][Nodejs]如何在socket.io连接期间解密Express会话cookie?,node.js,express,cookies,socket.io,express-session,Node.js,Express,Cookies,Socket.io,Express Session,成功登录后,用户名和用户名保存在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:

成功登录后,用户名和用户名保存在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中获取用户的
name
id
,然后将它们添加到
socketname

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

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


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

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

这些操作包括:

req.session.userId = userId;
req.session.name = name;
userId
name
将存储在服务器端的
MemoryStore

现在,让我们获取会话数据。
socket.request.headers.cookie的值将是如下字符串:

sid=s%3AfWB6_hhm39Z7gDKvAYFjwP885iR2NgIY.uT80CXyOKU%2Fa%2FxVSt4MnqylJJ2LAFb%2B770BItu%2FpFxk; io=msngndIn0v4pYk7DAAAU
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
  • 我们应该使用方法将字符串解析为JavaScript普通对象
  • 我们应该对已签名的cookie use方法取消签名。获取未签名的
    sid
  • 由于默认的服务器端会话存储是
    MemoryStore
    ,因此需要显式初始化它并调用WebSocket连接回调函数,以通过
    sid
    获取用户会话数据
  • 完整的工作示例:

    const session=require('express-session');
    const-app=require('express')();
    const http=require('http')。服务器(应用程序);
    const io=require('socket.io')(http);
    const bodyParser=require('body-parser');
    const cookieParser=require('cookie-parser');
    const cookie=require('cookie');
    const alluser=[{id:1,名称:'Admin',用户名:'Admin',密码:'Admin'}];
    const MemoryStore=新会话。MemoryStore();
    use(bodyParser.json());
    use(bodyParser.urlencoded({extended:true}));
    应用程序使用(
    会议({
    商店:MemoryStore,
    名称:“sid”,
    resave:false,
    saveUninitialized:false,
    秘密:“秘密密码!”,
    曲奇:{
    httpOnly:false,
    最大值:1000*60*60*24*30,
    sameSite:没错,
    },
    }),
    );
    应用程序获取(“/”,(请求,请求)=>{
    res.sendFile(uu dirname+'/index.html');
    });
    app.post('/login',(req,res)=>{
    const{username,password}=req.body;
    console.log(用户名、密码);
    如果(用户名和密码){
    const user=Allusers.find((user)=>user.username==用户名和user.password==密码);
    console.log(用户);
    如果(用户){
    req.session.userId=user.id;
    req.session.name=user.name;
    返回res.redirect('/');
    }
    }
    res.redirect('/login');
    });
    io.on('连接',(套接字)=>{
    log(“已连接的用户”);
    const cookieString=socket.request.headers.cookie;
    log('cookieString:',cookieString);
    如果(cookieString){
    const cookieParsed=cookie.parse(cookieString);
    log('cookieParsed:',cookieParsed);
    if(cookieParsed.sid){
    const sidParsed=cookieParser.signedCookie(cookieParsed.sid,'secretCode!');
    console.log(已解析);
    get(sidpassessed,(err,session)=>{
    如果(错误)抛出错误;
    log('user session data:',JSON.stringify(session));
    const{userId,name}=session;
    log('userId:',userId);
    console.log('name:',name);
    });
    }
    }
    });
    http.listen(3000,()=>{
    console.log('监听*:3000');
    });
    
    您将获得会话数据
    userId
    name
    ,如下所示:

    sid=s%3AfWB6_hhm39Z7gDKvAYFjwP885iR2NgIY.uT80CXyOKU%2Fa%2FxVSt4MnqylJJ2LAFb%2B770BItu%2FpFxk; io=msngndIn0v4pYk7DAAAU
    
    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
    

    源代码:

    似乎以前有人问过这个问题。您可以在此处阅读有关express和socket.io之间共享会话的信息:。另外,如果您不想使用该中间件。您可以阅读关于JWTI已经有签名cookie值的内容。我只想解码它,这样我就可以将它与存储的数据库相匹配。我可以在没有任何中间件的情况下进行分析吗?如果你有cookie,你可以使用:
    const cookieParser=require('cookie-parser')
    cookieParser.signedCookie(cookie,secret)
    @Sahee是的,我尝试过,但它不起作用。cookie值:
    s:1ixMMHeWxJ2-MnSNDQpW8lWFKpjQ9Z_.tD8jPkfgwnwAFI3EjNuZ95LknqGF/hgT07vA6pY315Q
    。它返回
    1ixMMHeWxJ2-MnSNDQpW8lWFKpjQ9Z_s
    。我期待一个像1或2这样的数字,即用户ID。代码:var-cookieData=cookie.parse(socket.handshake.headers.cookie)['sid']var-a=cookieParser.signedCookie(cookieData,secretKey)@Sahee即使使用中间件也没有解决问题。我按照这里的步骤操作,但无法访问sid。使用
    socket.request.session
    之后,我得到的只是:
    {“cookie”:{“originalMaxAge”:2592000000,“expires”:“2020-07-17T15:00:30.657Z”,“httpOnly”:false,“path”:“/”,“sameSite”:true}