javascript - 如何在服务器重启后存储带有 Passport 的连接用户?

标签 javascript node.js authentication passport.js passport-local

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

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

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

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

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

这里是片段:

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 填充 session 表?

最佳答案

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

Passport 无罪

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

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

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

现在我们证明了 Passport 的无罪,我们可以专注于 session 。

session

Express session 会自动创建一个 cookie,其中带有由 key 生成的签名 sid:

app.use(express.session({
secret :“键盘猫” })

sid 是 cookie id,express.session 使用它来将 session 数据(仅存储在服务器上)与客户端发出的请求链接起来。

持久 session

为了实现您想要做的事情(...我想做的事情),您必须使 session 持久化。如果您要使用 MongoDB,您可以使用 connect-mongo 将 session 数据存储到 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 中拥有了此信息。但是,当用户断开连接时,数据 session 将保留在数据库中。您可以使用兼容模式:

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

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

Detect IP changes (for security reasons)

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

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 中的事件,例如触摸 session 时触发的touch

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

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

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

嗯,这要归功于 connect-mongo

关于javascript - 如何在服务器重启后存储带有 Passport 的连接用户?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50437006/

相关文章:

javascript - node.js 将二进制字符串转换为数字

node.js - 无法在 Express 路由器内返回请求

ios - iOS 中的身份验证和 session 管理

javascript - 如何使用 switch 而不是多个 if 语句?

javascript - Coffeescript 类方法总是返回 false

javascript - redux connect mapStateToProps 在调度 Action 时不调用

javascript - ReactJS 的实时 API 监听器

linux - 使用 MIT Kerberos 作为 Windows AD 域的帐户域

javascript - 在 app init 上检查本地存储的 Angular 6 问题

javascript - 如何将<a>改为<div>?