Django REST框架:每用户限制
我有一些用户需要很高的节流能力,这样他们就可以经常使用这个系统。有没有一种简单的方法可以让他们比其他用户拥有更高的油门Django REST框架:每用户限制,django,django-rest-framework,throttling,Django,Django Rest Framework,Throttling,我有一些用户需要很高的节流能力,这样他们就可以经常使用这个系统。有没有一种简单的方法可以让他们比其他用户拥有更高的油门 我环顾四周,但没有发现任何东西。我找到了一种方法,扩展UserRateThrottle并将特殊用户添加到我的设置文件中 这个类只是覆盖了allow\u request方法,添加了一些特殊的逻辑来查看OVERRIDE\u THROTTLE\u RATES变量中是否列出了用户名: class ExceptionalUserRateThrottle(UserRateThrottle)
我环顾四周,但没有发现任何东西。我找到了一种方法,扩展UserRateThrottle并将特殊用户添加到我的设置文件中 这个类只是覆盖了
allow\u request
方法,添加了一些特殊的逻辑来查看OVERRIDE\u THROTTLE\u RATES
变量中是否列出了用户名:
class ExceptionalUserRateThrottle(UserRateThrottle):
def allow_request(self, request, view):
"""
Give special access to a few special accounts.
Mirrors code in super class with minor tweaks.
"""
if self.rate is None:
return True
self.key = self.get_cache_key(request, view)
if self.key is None:
return True
self.history = self.cache.get(self.key, [])
self.now = self.timer()
# Adjust if user has special privileges.
override_rate = settings.REST_FRAMEWORK['OVERRIDE_THROTTLE_RATES'].get(
request.user.username,
None,
)
if override_rate is not None:
self.num_requests, self.duration = self.parse_rate(override_rate)
# Drop any requests from the history which have now passed the
# throttle duration
while self.history and self.history[-1] <= self.now - self.duration:
self.history.pop()
if len(self.history) >= self.num_requests:
return self.throttle_failure()
return self.throttle_success()
我在定制Django REST节流后找到了解决方案 它会在3次登录尝试后阻止特定用户(阻止我的应用程序中显示的用户id)。匿名用户尝试6次登录后阻止IP地址 prevent.py:-
#!/usr/bin/python
from collections import Counter
from rest_framework.throttling import SimpleRateThrottle
from django.contrib.auth.models import User
class UserLoginRateThrottle(SimpleRateThrottle):
scope = 'loginAttempts'
def get_cache_key(self, request, view):
user = User.objects.filter(username=request.data.get('username'))
ident = user[0].pk if user else self.get_ident(request)
return self.cache_format % {
'scope': self.scope,
'ident': ident
}
def allow_request(self, request, view):
"""
Implement the check to see if the request should be throttled.
On success calls `throttle_success`.
On failure calls `throttle_failure`.
"""
if self.rate is None:
return True
self.key = self.get_cache_key(request, view)
if self.key is None:
return True
self.history = self.cache.get(self.key, [])
self.now = self.timer()
while self.history and self.history[-1] <= self.now - self.duration:
self.history.pop()
if len(self.history) >= self.num_requests:
return self.throttle_failure()
if len(self.history) >= 3:
data = Counter(self.history)
for key, value in data.items():
if value == 2:
return self.throttle_failure()
return self.throttle_success(request)
def throttle_success(self, request):
"""
Inserts the current request's timestamp along with the key
into the cache.
"""
user = User.objects.filter(username=request.data.get('username'))
if user:
self.history.insert(0, user[0].id)
self.history.insert(0, self.now)
self.cache.set(self.key, self.history, self.duration)
return True
from .prevent import UserLoginRateThrottle
....
....
....
class ObtainAuthToken(auth_views.ObtainAuthToken):
throttle_classes = (UserLoginRateThrottle,)/use this method here your login view
def post(self, request, *args, **kwargs):
....
....
Settings.py:-
#!/usr/bin/python
from collections import Counter
from rest_framework.throttling import SimpleRateThrottle
from django.contrib.auth.models import User
class UserLoginRateThrottle(SimpleRateThrottle):
scope = 'loginAttempts'
def get_cache_key(self, request, view):
user = User.objects.filter(username=request.data.get('username'))
ident = user[0].pk if user else self.get_ident(request)
return self.cache_format % {
'scope': self.scope,
'ident': ident
}
def allow_request(self, request, view):
"""
Implement the check to see if the request should be throttled.
On success calls `throttle_success`.
On failure calls `throttle_failure`.
"""
if self.rate is None:
return True
self.key = self.get_cache_key(request, view)
if self.key is None:
return True
self.history = self.cache.get(self.key, [])
self.now = self.timer()
while self.history and self.history[-1] <= self.now - self.duration:
self.history.pop()
if len(self.history) >= self.num_requests:
return self.throttle_failure()
if len(self.history) >= 3:
data = Counter(self.history)
for key, value in data.items():
if value == 2:
return self.throttle_failure()
return self.throttle_success(request)
def throttle_success(self, request):
"""
Inserts the current request's timestamp along with the key
into the cache.
"""
user = User.objects.filter(username=request.data.get('username'))
if user:
self.history.insert(0, user[0].id)
self.history.insert(0, self.now)
self.cache.set(self.key, self.history, self.duration)
return True
from .prevent import UserLoginRateThrottle
....
....
....
class ObtainAuthToken(auth_views.ObtainAuthToken):
throttle_classes = (UserLoginRateThrottle,)/use this method here your login view
def post(self, request, *args, **kwargs):
....
....
Django rest框架
我知道这是一条非常古老的线索,被接受的答案对我也很有帮助。我想展示如何设置多个用户速率限制,在本例中,为根用户提供额外的限制
from rest_framework.settings import api_settings
from django.core.exceptions import ImproperlyConfigured
class RootRateThrottle(UserRateThrottle):
"""
Limits the rate of API calls that may be made by a given user.
The user id will be used as a unique cache key if the user is
authenticated. For anonymous requests, the IP address of the request will
be used.
"""
def get_cache_key(self, request, view):
if request.user.is_authenticated:
ident = request.user.pk
else:
ident = self.get_ident(request)
self.rate = self.get_rate(request)
logger.debug(
"Throttling rate for %s: %s", request.user, self.rate
)
self.num_requests, self.duration = self.parse_rate(self.rate)
return self.cache_format % {
'scope': self.scope,
'ident': ident
}
def get_rate(self, request=None):
"""
Determine the string representation of the allowed request rate.
"""
if not getattr(self, 'scope', None):
msg = ("You must set either `.scope` or `.rate` for '%s' throttle" %
self.__class__.__name__)
raise ImproperlyConfigured(msg)
if request and request.user.is_superuser:
throttle_rates = settings.REST_FRAMEWORK["ROOT_THROTTLE_RATES"]
else:
throttle_rates = api_settings.DEFAULT_THROTTLE_RATES
try:
return throttle_rates[self.scope]
except KeyError:
msg = "No default throttle rate set for '%s' scope" % self.scope
raise ImproperlyConfigured(msg)
class ByMinuteRateThrottle(RootRateThrottle):
scope = 'minute'
class ByHourRateThrottle(RootRateThrottle):
scope = 'hour'
class ByDayRateThrottle(RootRateThrottle):
scope = 'day'
设置部分如下所示
'DEFAULT_THROTTLE_CLASSES': [
'threedi_api.throttling.ByMinuteRateThrottle',
'threedi_api.throttling.ByHourRateThrottle',
'threedi_api.throttling.ByDayRateThrottle',
],
'DEFAULT_THROTTLE_RATES': {
'minute': '100/min',
'hour': '1000/hour',
'day': '5000/day',
},
'ROOT_THROTTLE_RATES': {
'minute': '200/min',
'hour': '2000/hour',
'day': '10000/day',
},
谢谢你的回答!这个想法真的很好,而且肯定要包含在DRFI中。我还没有尝试将其推向上游,但如果有人尝试将其纳入主代码库,我会很高兴。对我来说,理想的解决方案应该是在django管理页面中按组对用户进行分组,并按这些组进行限制。尝试在你的代码和这个想法之间进行混合。如果我发现有什么东西会贴在这里,你为什么要这么做!?if user:self.history.insert(0,用户[0].id)user.id和time是两个不同的属性,对吗?这是如何回答这个问题的?用户询问的是如何增加特定用户的访问权限,而不是如何阻止登录失败的用户。这似乎很有用,但您将代码放在哪里?