【问题标题】:Express Session Different ExpirationExpress Session 不同的过期时间
【发布时间】:2018-04-03 09:10:40
【问题描述】:

我有以下代码在 Express 中创建会话。

app.use(session({
    secret: 'randomstring',
    saveUninitialized: false,
    resave: false,
    cookie: {
        secure: true,
        maxAge: 60000 * 60 /* 1 hour */
    }
}));

我主要用它在 Passport.js 中存储会话数据。目前,1 小时后用户会自动注销。或者会话结束,用户退出。

是否有一种简单的方法可以在会话中存储更多数据并为不同的信息设置不同的到期日期?假设我希望 Passport.js (req.session.passport.user) 会话数据的有效期为 1 小时。我希望另一条数据例如 (req.session.myDataA) 的有效期为 30 天。我希望另一条数据 (req.session.myDataB) 没有过期并永远保持活动状态。

有没有一种简单的方法可以在 Express Sessions 中实现这种行为?

【问题讨论】:

  • 有什么理由不使用localStorage
  • @GabrielBleu 本地存储在存储会话类型数据方面存在缺陷。 Cookie 与每个请求一起发送到特定域。本地存储没有。

标签: javascript node.js session express cookies


【解决方案1】:

您可以在另一个中间件中设置会话的 maxAge

代码:

// after session and passport middleware
app.use(function(req, res, next) {
    if (req.session.user) { // some condition
        req.session.cookie.maxAge = 1000 * 60 * 60 * 24 // 24 hours
    } else if (req.session.myData) {
        req.session.cookie.maxAge = 1000 * 60 * 60

    }
    // another condition

    // save the session
    req.session.save()

    // add next at the end of middleware 
    // so it can pas data edited to another middleware
    next()
})

【讨论】:

  • 好吧,如果我想将 user 和 myData 存储在会话中,那将无法正常工作。我想在会话中存储多个内容,并且每个内容都有不同的过期时间。
  • 请原谅,您是指会话中具有不同到期时间的“事物”吗?会话过期时它们是否应该过期?
  • 是的。所以我在会议中有很多事情。每个都有不同的到期时间。我希望自己永不过期的会话。只是里面的东西有不同的过期时间。
  • 它正在工作。它能够为不同的会话设置不同的过期时间。就我而言,我使用 Redis 数据库来存储会话数据,这段代码运行良好。
【解决方案2】:

您可以使用 cookie 并对不同的 cookie 名称设置不同的过期时间。因此,您可以拥有多个保存数据的 cookie,并且每个 cookie 都有特定的过期时间。

话虽如此,我想说会话和 cookie 都不是解决您问题的正确方法。我会保持您的会话精简并将数据存储在数据库中。考虑到您正在使用会话,您可以使用 Redis 并存储过期数据。您可以将 Redis 中的密钥分配给您的会话。例如:

req.session.myDataA = 'user_id:myDataA'
req.session.myDataB = 'user_id:myDataB'

在 Redis 中设置数据时,可以使用密钥 user_id:myDataA 并将其设置为过期。

// Will expire in 1 hour
SET user_id:myDataA "your data"
EXPIRE user_id:myDataA 3600

虽然密钥仍在会话中,但您可以检查该值是否为 null 或具有您期望的数据。

我知道这听起来可能有点复杂,但即使作为会话的良好做法,您真的不希望存储大量数据,超出参考键,因为它变得非常难以管理。

如果您使用的是 MongoDB,您还可以将文档设置为过期。但是,如果您不使用其中任何一个,Redis 通常是最容易设置的并且是一个很好的会话存储。

编辑:

如下所述,与其在不同的时间范围内使会话过期,不如在数据中设置一个具有过期时间的字段。然后,当您获取该数据时,检查它是否已过期(即 1 小时、30 天等)。

【讨论】:

  • 我的意思是现在我只在会话中存储用户 ID。但是 Passport.js 处理了大部分。我认为这个答案比我正在寻找的要复杂一些。如果可能的话,我想与我现有的 Passport.js 实现集成,并尽量保持它的高水平。
  • 可能最简单的解决方案是在数据中设置一个带有过期时间的字段,而不是在不同的时间范围内使会话过期。然后,当您获得该数据时,检查它是否已过期(即 1 小时、30 天等)。