如何在服务器重新启动时使用通行证存储已连接的用户?

How to store connected users with passport across server reboot?

我在玩passport-local。它的使用非常简单,但是 passport 在 cookie-session-id 和连接的用户之间建立关系的方式对我来说仍然很神秘。

我想将连接的会话存储在数据库中,以便:

从下面这个不起作用的片段中,您可以看到我有两个集合:

这里是片段:

import passport from 'passport'
import LocalStrategy from 'passport-local'

import mongoose from 'mongoose'

var UserSchema = new mongoose.Schema({
  username: String,    
  password: String
})

var Sessions = new mongoose.Schema({
  session: String, // Sessions of connected users 
  username: { type: Schema.Types.ObjectId, ref: 'User' },
  ip: String, // IP of the connected user 
  lastSeen: Date, // When the user made his last request 
})

var User = mongoose.model('UserSchema')

我应该如何使用 passport 填充会话 table?

嗯,我想我明白了,我应该可以回答我自己的问题了。

护照无罪

Passport 不负责持久性,但 express.session 负责。 Passport 在 中间件 中添加了一个包装器来拦截 HTTP 请求并使用 LogOutusername 等方法和属性填充请求。

默认情况下 express.session 将数据存储到内存中,因此当服务器停止时这些数据将被销毁。 Passport 仅将一个字段存储到会话中:

{ passport: { user: 'user-id' }}

现在我们证明了 Passport,我们可以专注于会话。

会话数

Express session 会自动创建一个带有签名 sid 的 cookie,该 cookie 由秘密制成:

app.use(express.session({
秘密:'keyboard cat' })

这个 sid 是 cookie id,它被 express.session 到 link 会话数据(仅存储在服务器上)与来自客户端的请求一起使用。

持久会话

要实现您想做的事情(...我想做的事情),您必须使会话持久化。如果要使用 MongoDB,可以使用 connect-mongo 将会话数据存储到 Mongo 集合中:

const MongoStore = require('connect-mongo')(express.session);

var app = express();

app.configure(function() {
  app.use(express.session({     
    secret: 'keyboard cat', 
    rolling: true,
    store: new MongoStore({ url: 'mongodb://localhost/db', stringify: false })
  }));
  //...
}

当您启动服务器并且有人发出请求时,它会在数据库集合中添加一个条目:

{ 
    "_id" : "AcBXmfIXvz_y2Jp4nw1zfJvZTVPsCq7D", 
    "session" : {
        "cookie" : {
            "originalMaxAge" : null, 
            "expires" : null, 
            "secure" : null, 
            "httpOnly" : true, 
            "domain" : null, 
            "path" : "/"
        }, 
        "passport" : {
            "user" : NumberInt(1)
        }
    }, 
    "expires" : ISODate("2018-06-03T18:10:54.237+0000")
}

您可以看到 Passport 仅按照说明存储用户 ID。

总结

Know the connected users

现在,您在 MongoDB 中有了这些信息。然而,当用户断开连接时,数据会话将保留在数据库中。您可以使用兼容模式:

app.use(session({
    store: new MongoStore({
      url: 'mongodb://localhost/test-app',
      autoRemove: 'interval',
      autoRemoveInterval: 10 // In minutes. Default
    })
}));

自动从数据库中删除过期的会话。

Detect IP changes (for security reasons)

您必须将此信息存储到您的会话中:

req.session.ip = (req.headers['x-forwarded-for'] ||
     req.connection.remoteAddress ||
     req.socket.remoteAddress ||
     req.connection.socket.remoteAddress).split(",")[0];

Auto disconnect users not seen for a long time

您必须手动实施。您可以使用 MongoStore 中的 event,例如在触摸会话时触发的 touch

Change the session number across each request (for security reasons)

这个比较复杂,我还没有答案。跨连接更改 cookie sid 意味着重新生成新的会话 ID 并更新 MongoDB。我还没有有效的解决方案。

Keep the users connected across server reboot (useful for debugging, and server update)

好吧,感谢 connect-mongo