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 &amp;&amp; !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;
        }
    }