没有 req.session.save() 会话不会保存在 Node.js 中

Posted

技术标签:

【中文标题】没有 req.session.save() 会话不会保存在 Node.js 中【英文标题】:Sessions won't save in Node.js without req.session.save() 【发布时间】:2014-12-19 07:13:57 【问题描述】:

我正在构建一个使用 Node.js、Express 和 Redis 进行会话管理的网站。无论出于何种原因,如果我有一个会话变量(在此示例中为 isLoggedIn),并且我刷新页面,该变量不会被保存,但是,如果我在设置变量后调用 req.session.save(),它确实会被保存到 Redis(redis-cli 监视器显示这一点 - 不调用 save() 表明该变量不存在,而调用 save() 显示它)。

我正在使用它来设置和启动服务器:

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var swig = require('swig');
var session = require('express-session')
var RedisStore = require('connect-redis')(session);

var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();

// Configure the favicon first. This avoids other middleware from processing the request if we know the request is for the favicon.
app.use(favicon(__dirname + '/public/images/favicon.ico'));

// All other requests will require everything else.

// Set up the view engine.
app.set('view engine', 'html');
app.set('views', path.join(__dirname, '/views'));
app.engine('html', swig.renderFile);

// Set up our logger.
app.use(logger('dev'));

// Set up JSON parsing.
app.use(bodyParser.json());

// Set up encoded URL parsing.
app.use(bodyParser.urlencoded());

// Set up the cookie parser.
app.use(cookieParser('thedogsleepsatnight'));

// Set up our session store. This will use Redis as our session management.
app.use(session(
    resave: true,
    saveUninitialized: true,
    secret: "thedogsleepsatnight",
    store: new RedisStore()
));

app.use(require('stylus').middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);

然后,在那条路线上,我有:

var express = require('express');
var router = express.Router();

router.get('/', function(req, res) 
    console.log(req.session.isLoggedIn);
    if (req.session.isLoggedIn) 
        console.log("Logged in!");
     else 
        console.log("Not logged in");
    

    res.render('index');
);

router.post('/login', function(req, res) 
    console.log("Going to set isLoggedIn. Currently: " + req.session.isLoggedIn);
    req.session.isLoggedIn = true;
    console.log("Set isLoggedIn. Currently: " + req.session.isLoggedIn);
);

module.exports = router;

从此,我应该能够导航到/login,将会话设置为 isLoggedIn 为 true,并且应该会自动保存到 Redis。之后,前往/ 应该告诉我我已登录。加载/login 确实设置了变量,第二个日志显示,但加载/ 表示我没有登录。redis-cli监控显示

1414076171.241836 "setex" "sess:FIDJ9qDbX_0u9pzlC6VZEW76zZcyiPME" "86400" "\"cookie\":\"originalMaxAge\":null,\"expires\":null,\"httpOnly\":true,\"path\":\"/\""

保存时,不包括isLoggedIn 变量,但添加req.session.save() 显示:

1414076475.601644 "setex" "sess:FIDJ9qDbX_0u9pzlC6VZEW76zZcyiPME" "86400" "\"cookie\":\"originalMaxAge\":null,\"expires\":null,\"httpOnly\":true,\"path\":\"/\",\"isLoggedIn\":true"

知道为什么我看到的所有示例都不使用req.session.save() 吗?

【问题讨论】:

你能指出其中一个例子吗?我本来预计需要使用 .save() 将更改推送到存储。 当然,tipstak.blogspot.com/2014/01/…。他设置 userId 而不调用保存。在另一个 SO 问题 ***.com/questions/14014446/… 中,解释说这一切都应该自动完成,其中 save() 只是为了手动保存。 您使用的中间件中是否有任何东西可以阻止或破坏 express-session 代理 end 方法的方式? github.com/expressjs/session/blob/master/index.js#L194 res.render 会执行那个方法吗? 刚查了一下,我在express-session的index.js文件中req.session.save的回调函数里放了一个console.log,说是修改后就保存成功了,但 redis-cli 监视器显示该变量不存在。 我刚刚注意到一些事情,保存时,isModified 返回 false,即使它是在变量更改后执行的。 【参考方案1】:

好的,所以,我想通了。我会在这里为碰巧被此问题抓住的其他人提供答案。

对于 GET 请求,服务器假定您要发回数据,并在路由完全处理后自动保存会话数据。

但是,对于 POST 请求(我正在使用的),没有做出相同的假设。会话状态仅在以下两种情况之一中保存 - 发送数据时(通过res.sendres.redirect 等),或者手动调用req.session.save()。我已经从 AJAX 请求中调用 /login,如果满足某些条件,我只是没有返回任何内容。在设置会话变量修复此问题后,让服务器向客户端响应一些数据。

【讨论】:

非常感谢您的回答,我已经挣扎了一段时间:) 谢谢伙计,我快疯了,因为我的会话在请求期间没有改变。你拯救了我的一天! 拯救了我的一天。我几乎疯了 五年后,仍然有帮助 感谢您的回答,五年后它仍然很有帮助。这应该记录在某处

以上是关于没有 req.session.save() 会话不会保存在 Node.js 中的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Django 不退出会话? .get 函数也不再像 .all 函数那样亮起?数据库中没有显示任何内容

没有 Hibernate Session 绑定到线程,并且配置不允许在这里创建非事务性会话

有没有办法在不关闭当前会话的情况下“刷新”终端/iTerm?

创建没有 express 的会话

Teradata DBS状态为7:系统在没有PE的情况下运行 - 不允许进行会话

没有 cookie 的 PHP 会话