在Heroku应用程序的多个dynos上设置Express应用程序会话

4
我已经使用express(node.js)+ mongodb在单个Heroku dyno上实现了一些用户认证,一切正常。然而,当我增加dynos的数量(超过1),我无法登录,我一直被重定向到我的登录页面,这意味着我的会话还没有设置。这是我的代码:
checkCookies = function(req, res, next) {
  if(req.session.user){
   res.locals.user = req.session.user;
   next();
  }
  else{
    res.redirect('/login');
  }
};
app.use(express.cookieParser());
  app.use(express.session({ secret: '0GBlJZ9EKBt2Zbi2flRPvztczCewBxXK',
  cookie: {httpOnly: true, maxAge:14*24*60*60*1000}
  }));

如何使用mongodb在express/node.js中处理共享会话的最佳解决方案是什么?

4个回答

6
上述答案误导了人们,暗示在Heroku的多个dynos之间不能共享基于cookie的会话。如果我使用cookie-session而不是express-session,则可以跨多个dynos使用基于cookie的会话。这个主题中第一个帖子缺少的是secret值未传递给cookie解析器。这意味着每次进程重新启动或新的dyno启动时,node都会为解析器分配一个随机哈希值。对我有用的是执行以下操作:
app.use(express.cookieParser('0GBlJZ9EKBt2Zbi2flRPvztczCewBxXK'))
app.use(express.session({
  secret: '0GBlJZ9EKBt2Zbi2flRPvztczCewBxXK',
  cookie: { httpOnly: true, maxAge: 14 * 24 * 60 * 60 * 1000 },
}))

很棒的答案,知道可以指定cookie密钥是很好的。 - Adam Reis
难道不应该使用cookieSession而不是express.session吗?就像文档中所示const cookieSession = require('cookie-session') - pmrotule

5
使用connect-mongo模块与express配合使用。
var http    = require('http'),
    express = require('express'),
    session = require('connect-mongo')(express)

然后在您的工作人员设置会话中进行外部存储。以下代码将使用来自Mongo、Cookie和额外标头的会话,以允许跨域和JSONP。

app.configure(function() {
  app.use(express.cookieParser());
  app.use(express.session({
    store: new session({
      db: 'sessions'
    }),
    secret: 'yoursecret',
    cookie: {
      path: '/',
      maxAge: 1000 * 60 * 60 * 24 // 1 day
    }
  }));
  app.use(function(req, res, next) {
    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Origin', req.headers.origin);
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
    next();
  });
  app.set('jsonp callback', true);
});

谢谢您进一步的解释!您能告诉我允许跨域和jsonp的优点吗?或者告诉我在哪里可以阅读相关内容?我已经尝试了谷歌搜索,但没有找到有用的信息。 - Cyril Gaillard
1
如果您拥有example.com网站,并从其JS AJAX请求调用api.com - 这将是您的节点应用程序,那么由于安全限制,大多数浏览器将不允许这样做。 您必须在服务器端启用此功能以允许从其他域访问,并且如果需要支持旧版浏览器,则必须添加JSONP并使用它。 如果您想共享会话cookie数据,您需要向ajax请求添加额外的位,对于jQuery,它将是xhrFields:{withCredentials:true}。 在此处查看更多信息:http://goo.gl/Y1XK0 - moka

5

非常感谢!一切已在10分钟内安装完成。 - Cyril Gaillard

0

对于任何想要快速复制/粘贴解决方案的人,如果想要更加更新的话,可以基本上按照Dan上面发布的链接或者使用我下面的代码片段:

var session = require('express-session');
var MongoStore = require('connect-mongo')(session);
var mongoose = require('mongoose'); // if using mongoose

mongoose.connect(connectionOptions); // if using mongoose

app.use(cookieParser());

app.use(session({
    store: new MongoStore({mongooseConnection: mongoose.connection}),
    secret: '0GBlJZ9EKBt2Zbi2flRPvztczCewBxXK',
    cookie: {
        path: '/',
        maxAge: 1000 * 60 * 60 * 24 // 1 day
    }
}));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接