没有 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#L194res.render
会执行那个方法吗?
刚查了一下,我在express-session的index.js文件中req.session.save的回调函数里放了一个console.log,说是修改后就保存成功了,但 redis-cli 监视器显示该变量不存在。
我刚刚注意到一些事情,保存时,isModified 返回 false,即使它是在变量更改后执行的。
【参考方案1】:
好的,所以,我想通了。我会在这里为碰巧被此问题抓住的其他人提供答案。
对于 GET 请求,服务器假定您要发回数据,并在路由完全处理后自动保存会话数据。
但是,对于 POST 请求(我正在使用的),没有做出相同的假设。会话状态仅在以下两种情况之一中保存 - 发送数据时(通过res.send
、res.redirect
等),或者手动调用req.session.save()
。我已经从 AJAX 请求中调用 /login,如果满足某些条件,我只是没有返回任何内容。在设置会话变量修复此问题后,让服务器向客户端响应一些数据。
【讨论】:
非常感谢您的回答,我已经挣扎了一段时间:) 谢谢伙计,我快疯了,因为我的会话在请求期间没有改变。你拯救了我的一天! 拯救了我的一天。我几乎疯了 五年后,仍然有帮助 感谢您的回答,五年后它仍然很有帮助。这应该记录在某处以上是关于没有 req.session.save() 会话不会保存在 Node.js 中的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Django 不退出会话? .get 函数也不再像 .all 函数那样亮起?数据库中没有显示任何内容
没有 Hibernate Session 绑定到线程,并且配置不允许在这里创建非事务性会话
有没有办法在不关闭当前会话的情况下“刷新”终端/iTerm?