PHP:一种存储登录尝试次数的方法


PHP: a way to store the number of login attemps?

如果在任何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分钟的时间间隔内倒计时,表可能会随着所有这些数据而变得非常巨大,并减缓系统。。。它还需要维护。

那么,你能给我一些更方便的建议吗?。。。

我会存储最后x次尝试的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..., ...)

试试看。如果你非常担心the table could potentially grow very huge with all this data ,我建议你使用redis

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

DOC中String的一个用例

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

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

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