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; } }