我想使用websockets来跟踪用户上次看到的时间,以及他们当前的在线状态(如果他们当前已经过身份验证并使用该应用程序)。
我有适用于应用程序某些部分的策略,因此用户将登录,然后转到策略适用的概述。
如果用户未经过身份验证,或者他们是,但会话信息与数据库的会话信息冲突,则概述将以notFound响应。
如果这些简单检查通过,则用户存在,因此应创建两个事件处理程序:
以下是政策代码:
const schedule = require('node-schedule')
var sheduledJob
module.exports = async function isSignedIn(req, res, next) {
// If the user has not signed in, pretend the page does not exist
if (!req.session.app || !req.session.app.userId) return res.notFound()
// Store the users id
let userId = req.session.app.userId
try {
// Update the user
var users = await User.update({
id: userId
})
.set({
last_accessed: new Date().getTime(),
online: true
})
.meta({
fetch:true
})
} catch (err) {
// Handle errors
return res.serverError(err.message)
}
// If the user does not exist
if (!users || users.length !== 1) {
console.log('policies/isSignedIn: no matching user '+userId)
// Sign the user out
delete(req.session.app)
// Pretend the page does not exist
return res.notFound()
}
// When the user exists
else {
// When there is a new client connection
var io = sails.io
io.on('connection', socket => {
console.log("==> Socket Connection Established")
console.log(socket.id, socket.request.headers.cookie.replace('sails.sid=',''))
// Cancel an existing job if one exists
if (sheduledJob) sheduledJob.cancel()
// Shedule a job to notify the client when the session has expired
var d = req.session.cookie._expires
sheduledJob = schedule.scheduleJob(d, () => {
console.log('The cookie has expired')
// The client should return to the auth page (will fire disconnecting when doing so)
req.socket.emit('logout', true)
})
// When the client is disconnecting
socket.on('disconnecting', async reason => {
console.log('Client disconnecting')
// As of Sails v1.0.0-46 reason is undefined when the application is lowering
if (reason) {
try {
// Update the user
var users = await User.update({
id: userId
})
.set({
last_accessed: new Date().getTime(),
online: false
})
} catch (err) {
// Handle errors
return res.serverError(err.message)
}
}
})
})
// Proceed as the user exists and we can handle the disconnecting event
return next()
}
};
我遇到的问题是,这会在最初加载页面时起作用,但如果我重新加载概述页面,那么我最终会遇到重复的事件处理程序:
加载页面一次(记住会话年龄为10秒进行测试):
==> Socket Connection Established
<socketId> <sessionId>
The cookie has expired
Client disconnecting
但如果我重新加载页面:
==> Socket Connection Established
<socketId> <sessionId>
Client disconnecting
==> Socket Connection Established
<socketId> <sessionId>
==> Socket Connection Established
<socketId> <sessionId>
The cookie has expired
Client disconnecting
Client disconnecting
所以我认为没关系,如果是这样的话那么我可以为事件监听器创建一个命名函数,然后最初删除事件监听器:
const schedule = require('node-schedule')
var sheduledJob
function connectionHandler(req, res, socket) {
console.log("==> Socket Connection Established")
console.log(socket.id, socket.request.headers.cookie.replace('sails.sid=',''))
...same as before...
}
module.exports = async function isSignedIn(req, res, next) {
...
// When the user exists
else {
// When there is a new client connection
var io = sails.io
var nsp = io.of('/')
nsp.removeListener('connection', connectionHandler)
io.on('connection', socket => connectionHandler(req, res, socket))
// Proceed as the user exists and we can handle the disconnecting event
return next()
}
};
但是这导致了相同的重复处理程序,所以我从处理程序中删除了所有req / res代码:
function connectionHandler(socket) {
console.log("==> Socket Connection Established")
console.log(socket.id, socket.request.headers.cookie.replace('sails.sid=',''))
socket.on('disconnecting', async reason => {
console.log('Client disconnecting')
})
}
在创建事件时进行修改:
io.on('connection', connectionHandler)
结果按照我的意图工作,重新加载页面时没有创建任何重复的事件处理程序:
==> Socket Connection Established
<socketId> <sessionId>
Client disconnecting
==> Socket Connection Established
<socketId> <sessionId>
有人可以向我解释我在哪里出错了,我真的不明白为什么:
io.on('connection', socket => connectionHandler(req, res, socket))
重复事件处理程序的结果,而:
io.on('connection', connectionHandler)
不是吗?
如果有人可以提出任何有关我在这里出错的建议,或者我如何能够更好地达到预期的结果,那么我们将非常感谢,非常感谢!
以下是我过去常用的一些参考资料:
答案 0 :(得分:0)
我做了一些似乎已经解决的改变:
const schedule = require('node-schedule')
var sheduledJob;
module.exports = async function isSignedIn(req, res, next) {
// If the user has not signed in, pretend the page does not exist
if (!req.session.app || !req.session.app.userId) return res.notFound()
// Store the users id and ip
let userId = req.session.app.userId
let userIp = req.headers['x-real-ip']
try {
// Update the user
var users = await User.update({
id: userId
})
.set({
last_accessed: new Date().getTime(),
last_accessed_ip: userIp,
online: true
})
.meta({
fetch:true
})
} catch (err) {
// Handle errors
return res.serverError(err.message)
}
// If the user does not exist
if (users.length !== 1) {
console.log('policies/isSignedIn: no matching user '+userId)
// Sign the user out
delete(req.session.app)
// Pretend the page does not exist
return res.notFound()
}
// When the user exists
else {
// When there is a new client connection
var io = sails.io
io.on('connection', function connectionHandler(socket) {
// console.log("==> Socket Connection Established")
// console.log(socket.id, socket.request.headers.cookie.replace('sails.sid=',''))
// Cancel the existing job if one exists
if (sheduledJob) sheduledJob.cancel()
// Shedule a job to notify the client when the session has expired
var d = req.session.cookie._expires
sheduledJob = schedule.scheduleJob(d, () => {
//console.log('The cookie has expired')
// Sign the user out
delete req.session.app
// The client should return to the auth page
socket.emit('session-expired', 'Your session has expired!')
})
// When the client is disconnecting
socket.on('disconnecting', async function disconnectingHandler(reason) {
//console.log('Client disconnecting: '+reason)
// Cancel the existing job if one exists
if (sheduledJob) sheduledJob.cancel()
// Remove any event handlers that were created
io.sockets.removeAllListeners('connection')
io.sockets.removeAllListeners('disconnecting')
// As of Sails v1.0.0-46 reason is undefined when the application is lowering
if (reason) {
try {
// Update the user
var users = await User.update({
id: userId
})
.set({
last_accessed: new Date().getTime(),
last_accessed_ip: userIp,
online: false
})
} catch (err) {
// Handle errors
return res.serverError(err.message)
}
}
})
})
// Proceed as the user exists and we can handle the disconnecting event
return next()
}
};
我认为这里的主要问题是我没有正确删除事件监听器,这需要在解除断开连接事件时发生。
根据https://github.com/expressjs/session#rolling,每个请求刷新的会话都需要向config.sessions添加rolling: true
,到期日期由config.session.cookie.maxAge确定。