我正在使用ExpressJS中间件来检查数据库中的用户ip并停止响应用户,如果最后一小时有超过7次登录失败,我在数据库连接之前使用检查'/',如果一切正常,则不会发送垃圾邮件数据库。但事实证明,当中间件访问数据库并在回调中进行检查时,第一个else
中的代码会运行。这是我的中间件:
// check for failed logins from this ip in db
// if allowed number exceeded - stop responding
app.use(function (req, res, next) {
if(req._parsedUrl.pathname === '/') {
MongoClient.connect(databaseUri || 'mongodb://localhost:27017/dev', function (err, db) {
assert.equal(err, null);
var failedLogins = db.collection('FailedLogins');
failedLogins.find({ip: req._remoteAddress}).toArray(function (err, results) {
assert.equal(err, null);
console.log('db check');
// if ip is in FailedLogins collection
if (results.length) {
// if there are more than 7 logins and they haven't expired
if (results[0].failedLoginsNum >= 7 && parseInt(results[0].expiration) >= parseInt(Date.now())) {
res.end();
} else {
next();
}
} else {
next();
}
});
});
} else {
console.log('next');
next();
}
});
这是控制台输出:
db check
GET / 200 20.117 ms - -
next
GET /favicon.ico 200 207.559 ms - 1353
答案 0 :(得分:1)
这是预期的行为,因为建立了早于db连接的第二个请求,并且查找已完成查询。
首先,您不希望在每个请求上创建新连接,这是一种不好的做法。
考虑下一个代码:
dbProvider.js
'use strict';
const MongoClient = require('mongodb').MongoClient;
const CONNECTION_PATH = 'mongodb://localhost:27017/dev';
module.exports.init = cb => {
MongoClient.connect(CONNECTION_PATH, (err, db) => {
module.exports.db = db;
cb(err, db);
});
};
index.js
'use strict';
const express = require('express');
const app = express();
const dbProvider = require('./dbProvider');
const PORT = 8888;
dbProvider.init((err, db) => {
if(err) {
console.error(err);
process.exit(1);
}
app.listen(PORT, () => console.log(`Listening on port ${PORT}`));
});
在index.js中,我们等到建立连接,然后才监听HTTP请求。 下一步是登录,所以如果你想限制登录尝试我建议使用简单的中间件。
index.js已修改
'use strict';
const express = require('express');
const app = express();
const dbProvider = require('./dbProvider');
const PORT = 8888;
dbProvider.init((err, db) => {
if(err) {
console.error(err);
process.exit(1);
}
app.listen(PORT, () => console.log(`Listening on port ${PORT}`));
});
// middlewares
function checkAuth(req, res, next) {
// here check if userId in cookie and match to db record or check token
if (req.authenticated()) {
return next();
} else {
return res.send(401); // Respond "Unauthorized"
}
}
function checkLoginAttempts(req, res, next) {
let failedLogins = dbProvider.db.collection('FailedLogins');
failedLogins.find({ip: req._remoteAddress}).toArray(function (err, results) {
if(err) {
console.error(err);
return res.status(500).end();
}
console.log('db check');
if(!results.length) return next();
// if ip is in FailedLogins collection
// if there are more than 7 logins and they haven't expired
if (results[0].failedLoginsNum >= 7 && parseInt(results[0].expiration) >= parseInt(Date.now())) {
res.status(401).send('The maximum number of login attempts has been reached. Please try again in 1 hour.');
} else {
next();
}
});
}
// routes
app.use('/yourLoginEndPoint', checkLoginAttempts, (req, res) => {
// login process, set userId as cookie value or create token
});
app.use('/anyOtherEndPoint', checkAuth, (req, res) => {
// here you sure that user is authenticated
});
如果有任何问题让我知道