我正在玩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 请求,并使用 LogOut
或 username
等方法和属性填充请求。
默认情况下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/