nodejs实现黑名单中间件设计


Posted in NodeJs onJune 17, 2014

黑名单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);
NodeJs 相关文章推荐
Nodejs中读取中文文件编码问题、发送邮件和定时任务实例
Jan 01 NodeJs
在windows上用nodejs搭建静态文件服务器的简单方法
Aug 11 NodeJs
用NodeJS实现批量查询地理位置的经纬度接口
Aug 16 NodeJs
nodejs实现邮件发送服务实例分享
Mar 29 NodeJs
NodeJs模拟登陆正方教务
Apr 28 NodeJs
nodejs动态创建二维码的方法
Aug 12 NodeJs
nodejs实现爬取网站图片功能
Dec 14 NodeJs
NodeJS如何实现同步的方法示例
Aug 24 NodeJs
PHPStorm中如何对nodejs项目进行单元测试详解
Feb 28 NodeJs
详解微信小程序-获取用户session_key,openid,unionid - 后端为nodejs
Apr 29 NodeJs
Nodejs环境实现socket通信过程解析
Jul 03 NodeJs
一文秒懂nodejs中的异步编程
Jan 28 NodeJs
nodejs分页类代码分享
Jun 17 #NodeJs
nodejs npm包管理的配置方法及常用命令介绍
Jun 05 #NodeJs
nodejs npm install全局安装和本地安装的区别
Jun 05 #NodeJs
nodejs文件操作模块FS(File System)常用函数简明总结
Jun 05 #NodeJs
使用forever管理nodejs应用教程
Jun 03 #NodeJs
使用upstart把nodejs应用封装为系统服务实例
Jun 01 #NodeJs
nodejs获取本机内网和外网ip地址的实现代码
Jun 01 #NodeJs
You might like
一些常用的php简单命令代码集锦
2007/09/24 PHP
php中$_REQUEST、$_POST、$_GET的区别和联系小结
2011/11/23 PHP
基于PHP服务端图片生成缩略图的方法详解
2013/06/20 PHP
zf框架的校验器InArray使用示例
2014/03/13 PHP
php字符串按照单词进行反转的方法
2015/03/14 PHP
CodeIgniter控制器之业务逻辑实例分析
2016/01/20 PHP
Laravel框架路由和控制器的绑定操作方法
2018/06/12 PHP
Yii2.0框架模型添加/修改/删除数据操作示例
2019/07/18 PHP
Yii框架 session 数据库存储操作方法示例
2019/11/18 PHP
验证控件与Button的OnClientClick事件详细解析
2013/12/04 Javascript
JavaScript学习小结(一)——JavaScript入门基础
2015/09/02 Javascript
JavaScript实现显示函数调用堆栈的方法
2016/04/21 Javascript
微信小程序如何获知用户运行小程序的场景教程
2017/05/17 Javascript
Bootstrap Multiselect 常用组件实现代码
2017/07/09 Javascript
vue项目中实现图片预览的公用组件功能
2018/10/26 Javascript
JavaScript文本特效实例小结【3个示例】
2018/12/22 Javascript
js实现通过开始结束控制的计时器
2019/02/25 Javascript
详解微信小程序开发(项目从零开始)
2019/06/06 Javascript
20道JS原理题助你面试一臂之力(必看)
2019/07/22 Javascript
[31:29]完美世界DOTA2联赛PWL S3 INK ICE vs Magma 第一场 12.20
2020/12/23 DOTA
在Python的Django框架中创建语言文件
2015/07/27 Python
python中redis查看剩余过期时间及用正则通配符批量删除key的方法
2018/07/30 Python
在numpy矩阵中令小于0的元素改为0的实例
2019/01/26 Python
使用python爬取微博数据打造一颗“心”
2019/06/28 Python
如何使用Python进行PDF图片识别OCR
2021/01/22 Python
指针和引用有什么区别
2013/01/13 面试题
.NET是怎么支持多种语言的
2015/02/24 面试题
应届毕业生求职信范文分享
2013/12/26 职场文书
某集团股份有限公司委托书样本
2014/09/24 职场文书
2014年小学数学教师工作总结
2014/12/03 职场文书
领导工作表现评语
2015/01/04 职场文书
2015年度校学生会工作总结报告
2015/05/23 职场文书
法定代表人身份证明书
2015/06/18 职场文书
师范生见习自我总结
2015/06/23 职场文书
Keras多线程机制与flask多线程冲突的解决方案
2021/05/28 Python
MySQL 如何限制一张表的记录数
2021/09/14 MySQL