代码之家  ›  专栏  ›  技术社区  ›  nowox

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

  •  1
  • nowox  · 技术社区  · 6 年前

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

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

    • 了解已连接的用户
    • 检测IP更改(出于安全原因)
    • 长时间未看到自动断开连接的用户
    • 在每个请求中更改会话号(出于安全原因)
    • 在服务器重新启动期间保持用户连接(对于调试和服务器更新很有用)

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

    • 一个存储注册用户
    • 一个用于存储连接的用户

    这里的代码片段:

    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 ?

    1 回复  |  直到 6 年前
        1
  •  0
  •   nowox    6 年前

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

    护照是无罪的

    护照不负责坚持,但是 express.session 是。Passport在 中间件 截获HTTP请求并用方法和属性(如 LogOut username .

    默认 快速会议 将数据存储到内存中,以便在服务器停止时销毁此数据。Passport只在会话中存储一个字段:

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

    现在我们免除了护照的责任,我们可以专注于会议。

    会议

    快速会话自动创建带有签名的cookie sid 秘密制造:

    应用程序使用(快速会话({
    秘密:“键盘猫” })

    这个 希德 是cookie ID,它由 快速会议 将会话数据(仅存储在服务器上)与客户机发出的请求链接起来。

    持续会话

    为了实现你想做的(…我想做的是),你必须让会议持续下去。如果要使用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,如所述。

    总之

    了解已连接的用户

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

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

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

    检测IP更改(出于安全原因)

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

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

    长时间未看到自动断开连接的用户

    你必须手动实现。您可以使用 event 来自MongoStore,例如 touch 当触摸会话时触发。

    在每个请求中更改会话号(出于安全原因)

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

    在服务器重新启动期间保持用户连接(对于调试和服务器更新很有用)

    好吧,谢谢 连接蒙古人