2014-01-09 54 views
-1

我正在实现一个块登录,所以如果发生很多(10?)登录失败(如有人试图强制密码),帐户无法尝试登录几分钟(即使使用有效的密码) ...如何限制使用redis的登录尝试?

我虽然速率限制使用Redis的图案,并在redis.io他们提供了两种可能的实现:​​

但是他们给的问题双方,尤其是在并发或丢失命令的情况下。

你推荐什么解决方案?

回答

-1

我找到了一个可能的解决方案。这是伪代码:

FUNCTION LIMIT_API_CALL(key): 
value = INCR(key) 
IF value > 10 THEN 
    ERROR "too many requests" 
ELSE 
    EXPIRE(key, blockedTime) 
    PERFORM_API_CALL() 
END 

这似乎相比redis.io链接实现小幅转移问题,但我认为这是稳健的规定的问题,所以不存在内存泄漏,以及即使其中一个命令失败,TTL也会始终设置。

EDIT(一年后):

这一招已经部署在生产,具有以下除了解决第一个注释检测到的问题:

PERFORM_API_CALL的成功返回删除密钥,重置到期计数器:

FUNCTION LIMIT_API_CALL(key): 
value = INCR(key) 
IF value > 10 THEN 
    ERROR "too many requests" 
ELSE 
    IF (PERFORM_API_CALL()) 
     DEL(key) 
    ELSE 
     EXPIRE(key, blockedTime) 
END 
+0

这似乎是一个很好的简单快速的代码。我认为它可能会遇到一些与竞争条件或编码缺陷无关的问题。例如,如果您只想允许“每小时登录10次”,但用户每30分钟只尝试登录一次,在5小时内他们将被拒绝登录尝试另一整小时 - 这种行为更像是“在拒绝服务之前,每小时登录2次“。另一种情况:从第一次登录尝试到第九次,几乎一个小时过去了,但用户仍然只能在整个下一个小时再尝试一次。 – ChisholmKyle

+0

你当然是对的。然而,通过这个非常简单的技巧检测并解决了这个问题:成功登录后,密钥被移除(并且重置失败),因此只有失败才会触发增加的到期计数器。这允许攻击者尝试更多的组合,只要他知道什么时候会成功登录就会发生,但是对于每个到期单元的每次成功登录,他只能将速率提高一倍......这在现实世界中不会发生太多事情。 – Daren