node.js - [Express][Nodejs] 如何在 socket.io 连接期间解密 express-session cookie?
问题描述
登录成功后,用户的 userId 和 Name 保存在 cookie 中。
服务器.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' : '用户名'}
我可以使用 cookie 获取 cookie socket.handshake.headers.cookie
,但它是使用秘密字符串加密的。
如何解密 cookie 数据或验证用户Allusers
?
解决方案
对于您的情况,首先,您需要知道会话 id 是由生成函数生成的 - generateSessionId(默认情况下)。这意味着会话 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
- 我们应该使用cookie.parse(str, options)方法将字符串解析为 JavaScript 普通对象。
{
sid: 's:fWB6_hhm39Z7gDKvAYFjwP885iR2NgIY.uT80CXyOKU/a/xVSt4MnqylJJ2LAFb+770BItu/pFxk',
io: 'eeOnxhDIiPSE_0gfAAAm'
}
- 我们应该使用cookieParser.signedCookie(str, secret)方法取消签名的 cookie 。获取无符号
sid
:
fWB6_hhm39Z7gDKvAYFjwP885iR2NgIY
- 由于默认的服务器端会话存储是
MemoryStore
,所以需要显式初始化,并在 WebSocket 连接回调函数中调用store.get(sid, callback)来获取用户会话数据sid
。
完整的工作示例:
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');
});
您将获得会话数据userId
,name
如下所示:
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
推荐阅读
- javascript - Select2JS - 我的列表中有一个默认值
- apache-kafka - 访问 Kafka 流转换历史的选项?
- python - 如何使用交叉验证模型获取系数
- python - 收敛失败的例子
- angular - 如何在所有组件之间共享一个 api 数据实例?
- mysql - 对 HIVE 中多个表的联合相同列的简明查询
- angular - Angular 7 注册角色
- clojure - 如何使用 clojure 生成 yaml 文件而不是创建 esxi vmmachine?
- python - Numpy:如何将数组的最大值选择到另一个数组中
- android - 在 Android 应用中集成 Linkedin V2.0 / OAuth2.0