Node应用之间的共享会话?

9

我目前有两个独立的Node应用程序运行在两个不同的端口上,但它们共享相同的后端数据存储。我需要在这两个应用程序之间共享用户会话,以便当用户通过一个应用程序登录时,他们的会话可用,并且他们似乎已经登录到另一个应用程序中。在这种情况下,这是一个面向公众的网站和一个管理后端。

我们的设置如下:

  • 使用Express的Node
  • 使用Local Strategy处理身份验证
  • 使用connect-redis通过redis共享会话
  • 我们的域名看起来像这样:www.mydomain.com和adm.mydomain.com

关于会话(和Redis)的配置对于两个应用程序都是相同的:

session: {
    options: {
        secret: "my secret",
        cookie: {
            domain: "mydomain.com",
            maxAge:1000*60*60*24
        }
    },
    redis: {
        host: 'my host',
        maxAge: 86400000,
        secret: "my secret"
    }
}

在 app.js 中,会话相关的配置如下所示:
if ( app.settings.env === "production" ) {
    session.options.store = new RedisStore(session.redis);
}
app.use(express.session(session.options));
app.use(passport.initialize());
app.use(passport.session({ secret: 'a different secret' }));

我期望它能做什么:让我们在两个应用程序之间的cookie中看到相同的会话ID。

所以我的问题是:如何设置express、redis和passport,以便在不同子域之间共享会话?


2
我认为你可能需要指定 Cookie 域为“.mydomain.com”-- 注意前面的点号(.)。 - Linus Thiel
昨天我们在测试中使用了“*.mydomain.com”,但似乎没有起作用。今天早上我会再试一次,看看结果如何。 - jpittman
1
你输入了一个 *,对吧?那么,只需要前导点。我认为这就是使 cookie 可以从不同的子域中读取的原因。让我知道,我可以提供它作为答案。 - Linus Thiel
结果发现使用“.mydomain.com”也没有起作用。我们还在寻找解决方法...不过,感谢您的建议,Linus。 - jpittman
你最后解决了这个问题吗?这真的可能吗? - ac360
解决方案将在生成和存储会话ID的代码中。Redis本身只是存储和检索它被告知的内容。但是,您可以使用Redis的MONITOR命令查看集合和获取操作。我怀疑它将显示每个应用程序设置新会话。 - The Real Bill
2个回答

4
也许有点过时,但此时,Express-session可以识别cookie的域选项。根据源码:
function session(options){
  var options = options || {}
  //  name - previously "options.key"
    , name = options.name || options.key || 'connect.sid'
    , store = options.store || new MemoryStore
    , cookie = options.cookie || {}
      ...

以下是设置cookie的代码:

var Cookie = module.exports = function Cookie(options) {
  this.path = '/';
  this.maxAge = null;
  this.httpOnly = true;
  if (options) merge(this, options);
  ...

因此,类似以下代码可以用于当前的1.10.1主版本:

secret: "my secret",
    cookie: {
        domain: "mydomain.com",

谢谢提醒。我已经不在这个项目中,并且现在也不使用Node,但是这是一个好消息。 - jpittman

2
Express-session似乎无法识别cookies的"domain"选项,因此导致了您的问题。每个应用程序自动将存储会话ID的cookie与其域相关联,因此它不能被共享。
一种选择是编写自己的单点登录模块,以跨Web应用程序共享会话。它可能会在执行顺序相当早的app.use()声明中存在,并且只需创建一个单独的cookie(该cookie将跨域),创建一个单独的SSO会话ID,并将SSO ID存储在这个新cookie中。之后,您只需根据需要交叉填充req.session和req.sso-session即可。

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