nodejs实现黑名单中间件设计


本文向大家介绍nodejs实现黑名单中间件设计,包括了nodejs实现黑名单中间件设计的使用技巧和注意事项,需要的朋友参考一下

黑名单Schema:

/**
 * Created by YCXJ-wanglihui on 2014/5/28.
 */
'use strict';

var mongoose = require('mongoose'); var Schema = mongoose.Schema;

//1.短暂屏蔽 2.永久屏蔽 var degree = {TEMP:1, FOREVER:2};

/**  * 黑名单  * @type {Schema}  *  * @param ip {String} 黑名单Ip  * @param createAt {Date} 创建时间  * @param expireTime {Date} 如果是短暂屏蔽,屏蔽到期时间  * @param forbiddenDegree {Number} 屏蔽级别 1.短暂屏蔽 2.永久屏蔽  * @param reason {String} 屏蔽原因  */ var BlackList = new Schema({     ip:{         type: String,         index:true     },     createAt:{         type: Date,         default: Date.now     },     expireTime:{         type: Date     },     forbiddenDegree:{         type: Number,         default:degree.TEMP     },     reason:{         type: String,         default: '请求次数频繁'     } });

mongoose.model('BlackList', BlackList);

IP与提交记录Schema:

/**
 * Created by YCXJ-wanglihui on 2014/5/28.
 */

'use strict';

var mongoose = require('mongoose'); var Schema = mongoose.Schema; var ObjectId = Schema.ObjectId;

/**  * 记录参与调查问卷的回复与Ip  * @type {Schema}  *  * @param answerId {ObjectId} 回复Id  * @param createAt {Date} 创建时间  * @param ip {String} 参与回复的人Ip  */ var IpAnswerLog = new Schema({     answerId: {         type: ObjectId     },     createAt: {         type: Date,         default:Date.now     },     ip:{         type: String,         index:true     } });

mongoose.model('IpAnswerLog', IpAnswerLog);

相关Proxy代码:

/**
 * Created by YCXJ-wanglihui on 2014/5/28.
 */
'use strict';

var IpAnswerLog = require('../models').IpAnswerLog;

/**  * 新建并保存  * @param ipAnswerLog {Schema or dict}  * @param callback  */ var newAndSave = function(ipAnswerLog, callback){     if(ipAnswerLog instanceof IpAnswerLog){         ipAnswerLog.save(callback);     }else{         var m = new IpAnswerLog(ipAnswerLog);         m.save(callback);     } }

/**  * 一分钟内回复数  * @param ip  * @param callback  */ var countOneMinuteAnswer = function(ip, callback){     var endTime = Date.now();     var beginTime = endTime - 1000*60*1;     countIpAnswerByTime(beginTime, endTime, ip, callback); }

/**  * 一小时内回复数字  * @param ip  * @param callback  */ var countOneHourAnswer = function(ip, callback){     var endTime = Date.now();     var beginTime = endTime - 1000*60*60*1;     countIpAnswerByTime(beginTime, endTime, ip, callback); }

/**  * 一天内回复  * @param ip  * @param callback  */ var countOneDayAnswer = function(ip, callback){     var endTime = Date.now();     var beginTime = endTime - 1000*60*60*24;     countIpAnswerByTime(beginTime, endTime, ip, callback); }

/**  * 计算某段时间内回复数  * @param beginTime {Number} 开始时间 时间戳  * @param endTime   {Number} 结束时间 如果为null,使用当前时间 时间戳  * @param ip    {String} Ip地址  * @param callback  */ var countIpAnswerByTime = function(beginTime, endTime, ip, callback){     if(!endTime){         endTime = Date.now();     }     IpAnswerLog.count({ip:ip, '$and':{$lt:beginTime, $gt:endTime}}, callback); }

exports.countIpAnswerByTime =countIpAnswerByTime; exports.countOneDayAnswer = countOneDayAnswer; exports.countOneHourAnswer = countOneHourAnswer; exports.countOneMinuteAnswer = countOneMinuteAnswer; exports.newAndSave = newAndSave;

黑名单Proxy:

/**
 * Created by YCXJ-wanglihui on 2014/5/28.
 */
'use strict';
var BlackList = require('../models').BlackList;

/**  * 新建并保存  * @param backList {BlackList} or {dict} 黑名单数据  * @param callback  */ var newAndSave = function(backList, callback){     if(backList instanceof BlackList){         backList.save(callback);     }else{         var m = new BlackList(backList);         m.save(callback);     } }

/**  * 禁用Ip访问一小时  * @param ip {String}  * @param callback  */ var newAndSaveOneHourTempForbidden = function(ip, callback){     var expireTime = Date.now() + 1000*60*60;     newAndSaveTempForbidden(ip,expireTime, callback); }

/**  * 禁用一天  * @param ip {String}  * @param callback  */ var newAndSaveOneDayTempForbidden = function(ip, callback){     var expireTime = Date.now() + 1000*60*60*24;     newAndSaveTempForbidden(ip, expireTime, callback); }

/**  * 新建临时黑名单  * @param ip {String}  * @param expireTime {Number} 到期时间  * @param callback  */ var newAndSaveTempForbidden = function(ip, expireTime,callback){     var blackList = new BlackList({ip:ip, expireTime:expireTime, forbiddenDegree:1});     newAndSave(blackList, callback); }

/**  * 新建并保存永久黑名单  * @param ip  * @param callback  */ var newAndSaveForeverForbidden = function(ip, callback){     var blackList = new BlackList({ip:ip, forbiddenDegree:2});     newAndSave(blackList, callback); }

/**  * 判断是否在黑名单中  * @param ip {String} Ip地址  * @param callback  */ var isInBlackList = function(ip, callback){     getBlackListByIp(ip, function(err, blackList){         if(err){             callback(err);         }else if(blackList){             var currentDate = Date.now();             if(blackList.forbiddenDegree ===1 && blackList.expireTime> currentDate){                 removeBlackListByIp(ip, function(err){                     if(err){                         callback(err);                     }else{                         callback(null, false);                     }                 })             }else{                 callback(null, true);             }         }else{             callback(null, false);         }     }) }

/**  * 通过Ip获取黑名单条目  * @param ip  * @param callback  */ var getBlackListByIp = function(ip, callback){     BlackList.findOne({ip:ip}, callback); }

/**  * 根据Ip删除黑名单  * @param ip  * @param callback  */ var removeBlackListByIp = function(ip, callback){     getBlackListByIp(ip, function(err, blackList){         if(err){             callback(err);         }else if(blackList){             blackList.remove(callback);         }else{             callback(null,null);         }     }) }

exports.newAndSave = newAndSave; exports.isInBlackList = isInBlackList; exports.getBlackListByIp = getBlackListByIp; exports.removeBlackListByIp = removeBlackListByIp; exports.newAndSaveOneHourTempForbidden = newAndSaveOneHourTempForbidden; exports.newAndSaveOneDayTempForbidden = newAndSaveOneDayTempForbidden; exports.newAndSaveForeverForbidden = newAndSaveForeverForbidden; exports.newAndSaveTempForbidden = newAndSaveTempForbidden;

中间件详情:

/**
 * Created by YCXJ-wanglihui on 2014/5/28.
 */
'use strict';

var BlackListProxy = require('../../proxy').BlackListPorxy; var IpAnswerLogProxy = require('../../proxy').IpAnswerLogProxy; var EventProxy = require('eventproxy');

/**  * 判断是否需要将Ip移动至黑名单中  * @param req  * @param res  * @param next  */ var isNeedMoveToBlackList = function(req, res, next){     var ip = req.ip;     //判断是否在黑名单中     requireNotInBlackList(req, res, function(){         var ep = new EventProxy();         ep.fail(next);

        ep.all('minuteCount', 'hourCount', 'dayCount', function(minuteCount, hourCount, dayCount){             if(minuteCount > 10){                 BlackListProxy.newAndSaveOneHourTempForbidden(ip, function(err, blackList){                     if(err){                         return next(err);                     }else{                         return res.send('提交过于频繁,1小时后重试!');                     }                 });             }else if(hourCount > 100){                 BlackListProxy.newAndSaveOneDayTempForbidden(ip, function(err, blackList){                     if(err){                         return next(err);                     }else{                         return res.send('提交过于频繁,1天后重试!');                     }                 })             }else if(dayCount > 1000){                 BlackListProxy.newAndSaveOneDayTempForbidden(ip, function(err, blackList){                     if(err){                         return next(err);                     }else{                         return res.send('提交过于频繁,1天后重试!');                     }                 })             }else{                 return next();             }         })

        IpAnswerLogProxy.countOneMinuteAnswer(ip,ep.done('minuteCount'));         IpAnswerLogProxy.countOneHourAnswer(ip, ep.done('hourCount'));         IpAnswerLogProxy.countOneDayAnswer(ip, ep.done('dayCount'));     }); }

/**  * 中间件 要求Ip不在黑名单中  * @param req  * @param res  * @param next  */ var requireNotInBlackList = function(req, res, next){     var ip = req.ip;     BlackListProxy.isInBlackList(ip, function(err, result){         if(err){             next(err);         }else if(result){             return res.send('您的Ip禁止提交,如有疑问请联系lihui.wang@tulingdao.com');         }else{             next();         }     }) }

exports.isNeedMoveToBlackList = isNeedMoveToBlackList; exports.requireNotInBlackList = requireNotInBlackList;

在路由中使用:

//网页提交接口
router.post('/create', middleware.isNeedMoveToBlackList, paperAnswers.create);