0

我认为我对 django-ratelimit 的理解是不正确的。我正在使用 v3.0.0 但 v2.0 产生相同的结果。可以说我有这个代码:

@ratelimit(key='post:username', rate='5/h', block=True)
@ratelimit(key='post:tenant', rate='5/h', block=True)
@csrf_exempt
def index(request):
    print(request.POST["username"])
    print(request.POST["tenant"])
    print("")
    return HttpResponse('hallo', content_type='text/plain', status=200)

假设租户 A 提交用户名“Antwon” 6 次,那么租户 A 将被阻止 1 小时,这很好。但是,假设租户 B 也有一个用户“Antwon”,那么租户 B 的该用户将无法登录。我假设租户 B 的 Antwon 应该仍然能够登录,否则租户 A 可以 DOS 其他租户?

这是预期的行为还是我的实现不正确?

4

1 回答 1

0

我的理解是不正确的。这是 django-ratelimit 的创建者的回复:

你好呀!我认为对于多个速率限制如何交互以及缓存键如何设置/旋转可能存在一些混淆。

多个限制是 ORed 在一起的——也就是说,如果你失败了其中任何一个,你就失败了——但是顺序很重要。在这种情况下,首先测试外部限制 post:username,然后测试租户。如果用户成功,则视为一次尝试,无论以后发生什么。这就是用户不断累积尝试的原因。如果您希望租户先计算,您可以重新订购装饰器。然而...

如果您想要对(用户名,租户)对进行单一限制,您可以通过创建一个返回租户和用户名组合的可调用键(可能是 {tenant}\u04{username} 或哈希)将这两个字段与自定义逻辑结合起来他们在一起)。

在锁定租户方面,有几件事:

首先,ratelimit 使用交错的固定窗口策略,而不是滑动窗口。因此,根据速率、周期、键值和组,将有一些计算窗口。例如,对于 1 小时,11:03:29 将是重置时间,相同组合的下一次重置时间将是 12:03:29,然后是 13:03:29 等......缺点是如果您的限制为 100/h,您可以在重置点附近的短时间内执行 200 个请求。好处是计算是无共享的,可以独立完成,即使你不小心过早地重试,窗口也会重置。

其次,是的,如果您对用户提供的数据(例如用户名)进行硬块(而不是例如使用经过身份验证的用户),它会创建一个拒绝服务向量。在可能的情况下,另一种选择是使用 block=False,并执行类似要求验证码而不是完全阻塞的操作。

于 2020-12-03T16:14:09.570 回答