Node.js [Express][Nodejs]如何在socket.io连接期间解密Express会话cookie?
成功登录后,用户名和用户名保存在cookie中 server.jsNode.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:
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}