0.背景
等保测评中有一项“暴力刷登录接口”这个项目,也就是测试方用第三方工具短时间内大量向后台登录接口发送数据,看看登录接口的承压能力。线上的版本承载100次短时间接口后崩溃了。
然后开始修改。
1.方案一:使用redis记录用户登录信息
这个方案前面的版本已经实现了,同一个用户限制登录的模型
一个繁琐的限制不同用户登陆的模型 – 每天进步一点点 (longkui.site)
这个模型已经实现了限制同一个用户的登录功能,但是并不能满足上面需求,因为上方用不同的用户名暴力测试接口,那么这个功能显得就不那么优秀了,我们需要一个更强力的功能来实现这个要求。
2.方案二:限制同一IP的登录行为
实际上就是拦截通过一个IP的频繁请求行为,如果请求过于频繁则不响应此IP的任何请求。
代码如下:
private CopyOnWriteArrayList<ConcurrentHashMap<String,Long>> ipList = new CopyOnWriteArrayList<>();
/**
* 限制同一个ip登录
* 3秒只允许请求一次
* */
private boolean limitIPtimes(HttpServletRequest request){
try{
String userIp = request.getRemoteAddr();
ConcurrentHashMap<String,Long> ipMap = new ConcurrentHashMap<>();
if(ipList!=null && !ipList.isEmpty()){
for(ConcurrentHashMap<String,Long> myMap : ipList) {
if(myMap.get(userIp) != null) {
//同一IP 3秒内只能提交一次
if(System.currentTimeMillis() - myMap.get(userIp) < 3 * 1000){
myMap.put(userIp,System.currentTimeMillis());
return false;
}
}
}
if(ipList.size()==10) {
//放满10次请求 清空一次
ipList.clear();
}
}
ipMap.put(userIp,System.currentTimeMillis());
ipList.add(ipMap);
return true;
} catch (Exception e){
e.printStackTrace();
return false;
}
}