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爬虫抓取数据之编码问题
Jul 03 NodeJs
Ajax异步文件上传与NodeJS express服务端处理
Apr 01 NodeJs
nodejs入门教程六:express模块用法示例
Apr 24 NodeJs
Nodejs中使用captchapng模块生成图片验证码
May 18 NodeJs
nodejs集成sqlite使用示例
Jun 05 NodeJs
nodejs body-parser 解析post数据实例
Jul 26 NodeJs
ubuntu编译nodejs所需的软件并安装
Sep 12 NodeJs
nodejs socket服务端和客户端简单通信功能
Sep 14 NodeJs
NodeJS 中Stream 的基本使用
Jul 30 NodeJs
深入理解nodejs搭建静态服务器(实现命令行)
Feb 05 NodeJs
NodeJS 文件夹拷贝以及删除功能
Sep 03 NodeJs
图解NodeJS实现登录注册功能
Sep 16 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中GET变量的使用
2006/10/09 PHP
CodeIgniter删除和设置Cookie的方法
2015/04/07 PHP
服务器迁移php版本不同可能诱发的问题
2015/12/22 PHP
php处理单文件、多文件上传代码分享
2016/08/24 PHP
visual studio code 调试php方法(图文详解)
2017/09/15 PHP
ExtJS 2.0实用简明教程 之ExtJS版的Hello
2009/04/29 Javascript
关于viewport,Ext.panel和Ext.form.panel的关系
2009/05/07 Javascript
javascript操作select元素实例分析
2015/03/27 Javascript
js中利用tagname和id获取元素的方法
2016/01/03 Javascript
Jquery中map函数的用法
2016/06/03 Javascript
基于jQuery实现表格内容的筛选功能
2016/08/21 Javascript
微信小程序开发之麦克风动画 帧动画 放大 淡出
2017/04/18 Javascript
javascript中new Array()和var arr=[]用法区别
2017/12/01 Javascript
React 源码中的依赖注入方法
2018/11/07 Javascript
layui 数据表格 根据值(1=业务,2=机构)显示中文名称示例
2019/10/26 Javascript
浅谈webpack构建工具配置和常用插件总结
2020/05/11 Javascript
python实现SMTP邮件发送功能
2020/06/16 Python
python版本单链表实现代码
2018/09/28 Python
几个适合python初学者的简单小程序,看完受益匪浅!(推荐)
2019/04/16 Python
python3 dict ndarray 存成json,并保留原数据精度的实例
2019/12/06 Python
Pytorch 之修改Tensor部分值方式
2019/12/27 Python
pycharm 中mark directory as exclude的用法详解
2020/02/14 Python
CSS3教程:边框属性border的极致应用
2009/04/02 HTML / CSS
如何唤起类中的一个方法
2013/11/29 面试题
应届生妇产科护士求职信
2013/10/27 职场文书
创建文明学校实施方案
2014/03/11 职场文书
法律七进实施方案
2014/03/15 职场文书
可口可乐广告词
2014/03/20 职场文书
高中学生评语大全
2014/04/25 职场文书
学校对教师的评语
2014/04/28 职场文书
保险公司演讲稿
2014/09/02 职场文书
“四风”问题对照检查材料思想汇报
2014/09/16 职场文书
2014年军人思想汇报范文
2014/10/12 职场文书
伏羲庙导游词
2015/02/09 职场文书
2015年三年级班主任工作总结
2015/05/21 职场文书
Nginx tp3.2.3 404问题解决方案
2021/03/31 Servers