限制用户每秒进行有限的请求

时间:2012-01-04 12:27:19

标签: java security web-applications java-ee

环境:
基于Java-EE的Web应用程序


问题
需要限制用户在同一秒内发出超过5个(例如)请求(主要是BOT)


解决方案
作为一个基本设计,我计划在应用程序范围内有2个同步Map

Map<String, Map<Long, Integer>>

String用于请求的sessionId

Long用于当前的第二次表示

Integer是保留请求计数


过程:

第0步:

配置Filter以拦截每个请求

第1步:

确定地图     我会看到当前minute是否奇怪,然后我会在mapOne上添加数据,我将清除mapTwo

第2步:

流程图

int requestNoForThisSecond = mapXX.get(request.getSession().getId()).get(currentSecondRepresantationInLong);
if(requestNoForThisSecond <= 5){
          requestNoForThisSecond++; 
          mapXX.get(request.getSession().getId()).put(currentSecondRepresantationInLong, requestNoForThisSecond);
}else{
         response.sendRedirect();// redirect to some captcha page
    } 

第4步:

如果会话过期/用户注销

,也会删除会话条目

这是问题的基本设计

你们中的任何一个人有更好的想法/建议吗?

5 个答案:

答案 0 :(得分:3)

首先,我认为您应该忘记会话ID的想法,而是使用IP地址。您不希望机器人向您发送必要的cookie,以便您可以跟踪其会话,对吗?

其次,我认为你的方法不必要地复杂化。您只需要一个IP地址到时间数组[N]的映射,其中N是固定数字,即您计划每秒允许的请求数。 (我假设它会相对较低。)因此,每当您收到来自给定IP的请求时,您将数组内容向下移动一步,并将新请求的时间添加到数组末尾。然后,从最后一个索引的时间中减去数组索引0处的时间,这将为您提供IP向您发送N个请求所花费的时间,您可以将其转换为每秒请求数。

此外,您可能会发现此讨论很有趣:https://softwareengineering.stackexchange.com/questions/126700/development-of-a-bot-web-crawler-detection-system

答案 1 :(得分:1)

可能是一个非常糟糕的黑客但是......

如果您尝试将相同的长值推送到超过阈值并将其用作值,那么实现Set<Long>操作返回false的自定义.add()

然后代码如下:

if (!theMap.get(whatever()).add(secondInLong))
    // threshold reached

一个优点是它会禁止您当前代码中的竞争条件:如果仅同步您的地图,则不会保护对会话数的检查。有了这个解决方案,它就是。

或者使用某种锁定环绕代码,并使用“普通”地图。

进一步考虑这个想法,你甚至可以实现一个带委派的自定义Map。然后,在地图本身内计算“长秒”表示,您不需要处理它。

答案 2 :(得分:1)

5秒请求每0.2秒相当于1个请求。那么为什么不简单地使用一个Map存储sessionID和用户的最后一个System.nanoTime(),然后你的过滤器只需要进行快速评估,以检查自用户上次请求以来至少已经过了200ms。

答案 3 :(得分:1)

有一个Synchronizer Token Pattern。建议使用此模式以防止双重提交,跨站请求伪造等.Struts广泛使用此模式(示例在JavaRanch上提及)。


对于那些不知道Synchronizer Token Pattern如何工作的人,请点击这里:

  1. 用户请求页面。在服务器上,负责页面请求的控制器从页面中检索令牌(不是JSESSIONID)。
  2. 如果从请求返回的令牌与会话中找到的令牌匹配,则它是有效令牌,继续。
  3. 重置令牌(生成新令牌)并将其保存在会话中。因此,您可以每次都使用新令牌进行验证并返回同一页面。
  4. 在您的建议中,您必须对提交时间进行计时,检索会话令牌(使用HttpSessionListener)并限制您的请求呼叫。

    我希望这会有所帮助。

答案 4 :(得分:0)

听起来很合理,类似于this article中针对Spring&lt; - &gt; captcha集成的建议。