0

如果在任何 5 分钟间隔内有 5 个不正确,我想通过 IP 阻止所有请求,比如说 10 分钟。而且我正在考虑一种方法来存储这些数据,这种方式最不可能损害性能。

特别是关于如何设计数据库表和存储数据。

如果我为 IP 制作一个固定表作为主表,例如使用 mysql:

ip int(10) unsigned, primary key (ip)
attempts int(5),
lastaccess timestamp default current_timestamp

然后它会不充分地积累尝试......

另一方面,如果我用时间戳记录所有不正确的尝试,例如:

ip int(10) unsigned,
lastaccess timestamp default current_timestamp,
primary key (ip,lastaccess)

然后在 5 分钟的时间间隔内倒计时,表可能会因所有这些数据而变得非常庞大并减慢系统速度……它还需要维护。

所以,你能给我一些更方便的建议吗?...

4

2 回答 2

3

我会存储最后一次尝试的 IP 地址和时间戳。无论是在数据库中、memcached 类型的存储中,还是可能只是一些平面文件中,这取决于您预期的流量。

如果是数据库,您可以轻松查询类似COUNT(timestamps) GROUP BY ip WHERE timestamp [within last 5 minutes]的内容,偶尔使用简单的DELETE WHERE timestamp [over 5 minutes ago]. 清理可能发生在 cron 作业或垃圾收集系统中的每个 x 请求中。

如果是 memcached 或平面文件之类的东西,请将时间戳存储在 FIFO 数组中,即array(123456..., 123456..., ...)您不断截断的简单文件。

于 2012-07-25T07:48:20.020 回答
1

试一试。我建议redis以防你很担心the table could potentially grow very huge with all this data

为每个用户生成一个唯一 ID [很可能是 IP,但考虑来自同一网络的用户。例如:来自组织的用户将具有与所有传出请求相关联的相同 IP,即使来自不同的机器] 并使用STRING数据类型,键为唯一 ID,值作为计数器 [存储尝试次数]。

String来自 DOC的一个用例

使用 INCR 系列中的命令将字符串用作原子计数器:INCR、DECR、INCRBY。

字符串数据类型也支持过期。因此,您生成的所有密钥都将在 5 分钟内到期,一旦达到时间限制,它将自毁。您可以只读取计数器值来确定是否阻止用户。现在您不必担心随着时间的推移记录的数量

Redis 将所有数据都保存在内存中。我认为您也可能会获得一些性能改进

于 2012-07-25T08:00:26.477 回答