Nodejs中如何使session正常工作
Nodejs中如何使session正常工作
因为使用AIR做客户端(iOS也同样),所以没法用cookie,用的是CSRF方式来管理session,不知道对不对。
目标: 每个用户登录之后建立session,打印出他post的信息。每个用户有自己的session
时序:
- client (GET method access) -> express
- client got csrf token
- client (POST method with token) -> express
结果: 现在后面用户登录后覆盖前面用户的session,比如aaa登录,打印是aaa post: …, bbb登录之后,aaa窗口再post信息,打印就变成bbb post: … (应该是aaa post: … )。 现在的结果是好像所有用户共享一个session一样,查了很多资料也没明白,请指点迷津。
Got client login : aaa
Got client post : a11111111
aaa post times = 1
Got client login : bbb
Got client post : b222222222
bbb post times = 1
( === 以下是aaa用户的 === )
Got client post : a111111111
bbb post times = 1
代码如下:
var express = require('express');
var app = express.createServer();
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({secret:‘mySecret’}));
app.use(express.csrf());
function csrf(req,res,next) {
// res.locals.token = req.session._csrf;
res.locals.csrftoken = req.session._csrf;
next();
}
app.get(’/’,csrf,function(req,res){
req.session.user = req.query.username;
console.log('Got client login : '+req.query.username);
res.send('token='+req.session._csrf);
});
app.post(’/’,csrf,function(req,res)
{
console.log('Got client post : ‘+req.body.say);
if (typeof req.session.view != ‘undefined’)
{
req.session.view++;
}
else
{
req.session.view = 1;
}
console.log(req.session.user+’ post times = '+req.session.view);
});
app.listen(9001);
console.log(‘listen to 9001…’);
要解决这个问题,我们需要确保每个用户都有自己的独立 session
。在你的代码中,问题可能在于 session
的存储机制。默认情况下,Express 使用内存存储 session
数据,这会导致所有会话数据都存储在同一地方,从而导致多个用户之间的 session
数据相互干扰。
为了确保每个用户都有自己的独立 session
,你可以使用一个更可靠的 session
存储方案,例如 connect-mongo
或 connect-redis
。这里我们使用 connect-mongo
作为示例。
首先,你需要安装必要的依赖包:
npm install express express-session connect-mongo mongoose --save
然后,你可以修改你的代码以使用 connect-mongo
来存储 session
数据:
const express = require('express');
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
const mongoose = require('mongoose');
// 连接到 MongoDB
mongoose.connect('mongodb://localhost:27017/mydatabase', { useNewUrlParser: true, useUnifiedTopology: true });
const app = express();
app.use(express.json()); // 解析 JSON 请求体
app.use(express.urlencoded({ extended: true })); // 解析 URL 编码的请求体
// 配置 session 中间件
app.use(session({
secret: 'mySecret',
store: new MongoStore({ mongooseConnection: mongoose.connection }),
resave: false,
saveUninitialized: true
}));
app.use(express.csrf());
function csrf(req, res, next) {
res.locals.csrftoken = req.csrfToken();
next();
}
app.get('/', csrf, function(req, res) {
req.session.user = req.query.username;
console.log('Got client login : ' + req.query.username);
res.send('token=' + req.csrfToken());
});
app.post('/', csrf, function(req, res) {
console.log('Got client post : ' + req.body.say);
if (typeof req.session.view !== 'undefined') {
req.session.view++;
} else {
req.session.view = 1;
}
console.log(req.session.user + ' post times = ' + req.session.view);
res.send('Post received');
});
app.listen(9001, () => {
console.log('Server listening on port 9001');
});
关键点解释:
- MongoDB 连接:使用
mongoose
连接到 MongoDB 数据库。 - Session 配置:使用
express-session
和connect-mongo
来配置session
存储。store
参数指定了session
数据将被存储到 MongoDB 中。 - CSRF 保护:使用
express.csrf()
来生成 CSRF 令牌,并在每次请求中使用该令牌进行验证。
通过这些修改,每个用户的 session
将会被存储在 MongoDB 中,确保每个用户都有独立的 session
,不会相互干扰。
似乎是AIR的问题,在同一台PC上运行多个实例session是同一个,看了token发现的,在不同PC上运行就会是各自独立的session。所以上面代码应该是没问题的。
根据你的描述,问题在于session被多个用户共享。这通常是因为会话存储配置不正确或未正确设置CSRF令牌。在Express.js中,你可以使用express-session
中间件来管理session,并确保使用合适的存储后端来避免会话被共享。
以下是如何使用express-session
中间件并结合connect-mongo
作为存储后端的一个示例:
-
首先安装必要的依赖:
npm install express-session connect-mongo
-
更新你的代码以使用
connect-mongo
作为会话存储:const express = require('express'); const session = require('express-session'); const MongoStore = require('connect-mongo')(session); const bodyParser = require('body-parser'); const app = express(); // 使用body-parser中间件解析请求体 app.use(bodyParser.urlencoded({ extended: false })); // 使用express-session中间件,并指定MongoDB作为存储后端 app.use(session({ secret: 'mySecret', store: new MongoStore({ url: 'mongodb://localhost/session-db' }), resave: false, saveUninitialized: true })); app.use(express.csrf()); function csrf(req, res, next) { res.locals.csrfToken = req.csrfToken(); next(); } app.get('/', csrf, (req, res) => { req.session.user = req.query.username; console.log('Got client login : ' + req.query.username); res.send('token=' + req.csrfToken()); }); app.post('/', csrf, (req, res) => { console.log('Got client post : ' + req.body.say); if (typeof req.session.view !== 'undefined') { req.session.view++; } else { req.session.view = 1; } console.log(req.session.user + ' post times = ' + req.session.view); res.send('Posted successfully'); }); app.listen(9001, () => { console.log('Server is listening on port 9001'); });
通过上述修改,每个用户将拥有独立的会话数据,并且会话数据会被安全地存储在MongoDB数据库中,避免了会话数据被其他用户覆盖的问题。