等保基本要求里,对应用安全中身份鉴别要求有:应提供登录失败处理功能,可采取结束会话、限制非法登录次数和自动退出等措施。主要是为了防止口令尝试攻击。应用如果要搞等保测评,发现登录失败处理功能缺失的话,会被要求整改的。所以我们开发应用登录应该有失败处理规则。
以下我们用nodejs示例吧,先定义一个简单的规则吧:同一个客户端IP,在两分钟内连续登录失败三次,限制登录五分钟。
为此我们定义一个json数组loginfaillist,初始值为[],元素格式为{ip,firstfailtime,secondfailtime,failcount,permittime}
每次登录失败要执行一次调用addfail(now,ip)
function addfail(now,ip) {
item=loginfaillist.find(itm=>(itm.ip==ip));
if (item==undefined) { loginfaillist.push({ip:ip,firstfailtime:now,secondfailtime:now,failcount:1,permittime:now});}
else if (item.failcount==0) {
item.failcount=1;
item.firstfailtime=now;
}
else if (item.failcount==1) {
item.failcount=2;
item.secondfailtime=now;
}
else {
if (now.getTime()<item.firstfailtime.getTime()+120000) { item.failcount=0; item.permittime.setTime(now.getTime()+300000); }
else { item.firstfailtime=item.secondfailtime; item.secondfailtime=now; }
}
}
在登录认证逻辑处理中加入失败处理代码:
...
let clientip=req.header('x-forwarded-for')?req.header('x-forwarded-for'):req.ip;
let now=new Date();
let item=loginfaillist.find(itm=>(itm.ip==clientip));
if ((item!=undefined)&&(now<item.permittime)) {
res.json({msg:"该IP已触发登录异常,请于"+item.permittime.toLocaleTimeString()+"后再尝试"});//有失败记录,尚未到解禁时间则不执行登录,直接前端提示告警
}
else {
callauth(obj.uid, obj.upw, (err)=> {
if (err) {
...
addfail(now,clientip); //增加失败记录
}
else {
...
loginfaillist=loginfaillist.filter(itm=>(itm.ip!=req.ip));//一次登录成功则清空失败记录
...
}
})
}
...
例程里是拿账号和密码去认证源验证,现在登录认证方式很多,不一定都是这种类型,但是失败处理的思路是一样的,同学们可以自行发挥。