Nodejs中如何使session正常工作

Nodejs中如何使session正常工作

因为使用AIR做客户端(iOS也同样),所以没法用cookie,用的是CSRF方式来管理session,不知道对不对。

目标: 每个用户登录之后建立session,打印出他post的信息。每个用户有自己的session

时序:

  1. client (GET method access) -> express
  2. client got csrf token
  3. 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…’);


4 回复

要解决这个问题,我们需要确保每个用户都有自己的独立 session。在你的代码中,问题可能在于 session 的存储机制。默认情况下,Express 使用内存存储 session 数据,这会导致所有会话数据都存储在同一地方,从而导致多个用户之间的 session 数据相互干扰。

为了确保每个用户都有自己的独立 session,你可以使用一个更可靠的 session 存储方案,例如 connect-mongoconnect-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');
});

关键点解释:

  1. MongoDB 连接:使用 mongoose 连接到 MongoDB 数据库。
  2. Session 配置:使用 express-sessionconnect-mongo 来配置 session 存储。store 参数指定了 session 数据将被存储到 MongoDB 中。
  3. CSRF 保护:使用 express.csrf() 来生成 CSRF 令牌,并在每次请求中使用该令牌进行验证。

通过这些修改,每个用户的 session 将会被存储在 MongoDB 中,确保每个用户都有独立的 session,不会相互干扰。


似乎是AIR的问题,在同一台PC上运行多个实例session是同一个,看了token发现的,在不同PC上运行就会是各自独立的session。所以上面代码应该是没问题的。

除非NODE原生支持,严重不建议使用SESSION

根据你的描述,问题在于session被多个用户共享。这通常是因为会话存储配置不正确或未正确设置CSRF令牌。在Express.js中,你可以使用express-session中间件来管理session,并确保使用合适的存储后端来避免会话被共享。

以下是如何使用express-session中间件并结合connect-mongo作为存储后端的一个示例:

  1. 首先安装必要的依赖:

    npm install express-session connect-mongo
    
  2. 更新你的代码以使用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数据库中,避免了会话数据被其他用户覆盖的问题。

回到顶部