我正在使用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发布于 2016-08-05 16:01:11
这是预期的行为,因为建立了比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
});如果有任何问题,请告诉我
https://stackoverflow.com/questions/38781810
复制相似问题