之前提到使用ratelimit来限制访问频率,我的目的是根据用户来限制访问频率,但是实际上通过下面的代码并没有达到效果,如果用多个浏览器进行同时刷新,会存在跳过限制的情况
@ratelimit(key='user', rate='1/8s', block=True, method=('POST')) |
本来是不想重复造轮子的,但是由于这个轮子不大好用,于是只好重新造一个,基于redis可以使用下面的代码来实现(ttl为限制时长):
def set_method_limit(method_name, player_id, ttl): cash_name = 'RATELIMIT::METHOD=' + method_name + 'PLAYERID=' + str(player_id) cache.set(cash_name, method_name, ttl) def check_is_limit(method_name, player_id): cash_name = 'RATELIMIT::METHOD=' + method_name + 'PLAYERID=' + str(player_id) if cash_name in cache: return True return False def redis_ratelimit(method='ALL', block=False, ttl=5): def decorator(fn): @wraps(fn) def _wrapped(*args, **kw): # Work as a CBV method decorator. request = args[0] auth = request.META.get('HTTP_AUTHORIZATION', 'UNKNOWN') # 获取用户id 如果失败则用token try: auth = request.user.id print('PID= ' + str(auth)) except: pass token = str(auth).split(' ')[-1] if check_is_limit(method, token) and block: content = { 'status': 403, 'message': '大侠喝口茶,小女子给你讲个故事如何?\r\n 从前有座山,山上有座庙……', } return JsonResponse(content) # raise Redis_Rate_Limit() set_method_limit(method, token, ttl) return fn(*args, **kw) return _wrapped return decorator |
使用方法和retalimit一致:
@api_view(['POST', 'GET']) @redis_ratelimit(method='api_test', block=True, ttl=10) @csrf_exempt def api_test(request): """ 测试接口 http://192.168.1.195:8006/rest-api/battle/api-test/ :return: 普通数据测试 """ return json_response_message(status=API_SUCCESS, message=timezone.now().date()) |
redis 安装:
pip3 install django-redis |
redis 配置:
# redis配置 CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "CONNECTION_POOL_KWARGS": {"max_connections": 100} # "PASSWORD": "密码", } } } |
原创文章,转载请注明: 转载自 obaby@mars
本文标题: 《再谈《Django 限制访问频率》》