블랙리스트 스키마:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
//1. 임시 차단 2. 영구 차단
var grade = {TEMP:1, FOREVER:2};
/**
* 블랙리스트
* @type {Schema}
*
* @param ip {String} 블랙리스트 Ip
* @param createAt {Date} 생성 시간
* @paramexpirTime { Date} 임시 차단인 경우 차단 만료 시간
* @param allowedDegree {Number} 차단 수준 1. 임시 차단 2. 영구 차단
* @param 이유 {String} 차단 이유
*/
var BlackList = new Schema({
ip:{
유형: 문자열,
index:true
},
createAt: {
유형: 날짜,
기본값: Date.now
},
만료 시간:{
유형: 날짜
},
allowedDegree:{
유형: 숫자 ,
기본값:degree.TEMP
},
이유:{
유형: 문자열,
기본값: '자주 요청'
}
});
mongoose.model('BlackList', BlackList);
IP 및 제출 기록 스키마:
'엄격한 사용';
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: {
유형: ObjectId
},
createAt: {
유형: 날짜 ,
기본값:Date.now
},
ip:{
유형: 문자열,
인덱스:true
}
});
mongoose.model('IpAnswerLog', IpAnswerLog);
관련 프록시 코드:
var IpAnswerLog = require('../models').IpAnswerLog;
/**
* 새로 만들고 저장
* @param ipAnswerLog {스키마 또는 dict}
* @param 콜백
*/
var newAndSave = function(ipAnswerLog, 콜백){
if(ipAnswerLog 인스턴스of IpAnswerLog){
ipAnswerLog.save(콜백);
}else{
var m = new IpAnswerLog(ipAnswerLog);
m.save(콜백);
}
}
/**
* 1분 이내 답글 개수
* @param ip
* @param 콜백
*/
var countOneMinuteAnswer = function(ip, callback){
var endTime = Date.now();
var startTime = endTime - 1000*60*1;
countIpAnswerByTime(beginTime, endTime, ip, callback);
}
/**
* 1시간 이내 회신번호
* @param ip
* @param callback
*/
var countOneHourAnswer = function(ip, callback){
var endTime = Date.now();
var startTime = endTime - 1000*60*60* 1;
countIpAnswerByTime(beginTime, endTime, ip, callback);
}
/**
* 1일 이내 답변
* @param ip
* @param callback
*/
var countOneDayAnswer = function(ip, callback){
var endTime = Date.now();
var startTime = endTime - 1000*60*60* 24;
countIpAnswerByTime(beginTime, endTime, ip, callback);
}
/**
* 일정 시간 내 응답 횟수 계산
* @param startTime {Number} 시작 시간 타임스탬프
* @param endTime {Number} 종료 시간이 null인 경우 현재 시간 타임스탬프 사용
* @param ip {String} IP 주소
* @param 콜백
*/
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;
黑name单Proxy:
/**
* 新建并保存
* @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 콜백
*/
var RemoveBlackListByIp = function(ip, callback){
getBlackListByIp(ip, function(err, blackList){
if(err){
콜백 (err);
}else if(blackList){
blackList.remove(콜백);
}else{
콜백(null,null);
}
})
}
exports.newAndSave = newAndSave;
exports.isInBlackList = isInBlackList;
exports.getBlackListByIp = getBlackListByIp;
exports.removeBlackListByIp = RemoveBlackListByIp;
exports.newAndSaveOneHourTempForbidden = newAndSaveOneH ourTempForbidden;
수출. newAndSaveOneDayTempForbidden = newAndSaveOneDayTempForbidden;
exports.newAndSaveForeverForbidden = newAndSaveForeverForbidden;
exports.newAndSaveTempForbidden = newAndSaveTempForbidden;
中间件详情:
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;
라우팅에 사용:
코드 복사