如何为Django视图中的网页实现特定IP的DDOS防护
Django 应对DDoS攻击的IP封禁方案
问题分析
使用ratelimit库的limits装饰器时,触发的RateLimitException会导致全站崩溃,核心需求是仅封禁发起超限请求的IP,不影响正常用户访问。
解决方案
1. 捕获异常返回局部限制响应
直接捕获RateLimitException,针对超限IP返回429状态码,避免异常扩散导致全站故障。修改后的视图代码:
import ratelimit from ratelimit import limits, RateLimitException from django.http import HttpResponseTooManyRequests from django.shortcuts import render @limits(calls=5, period=10) def home_page(request): try: user_id = request.session.get("user_id") authorized = user_id is not None return render(request, template_name="index.html", context={"authorize": authorized}) except RateLimitException: return HttpResponseTooManyRequests("请求过于频繁,请稍后再试")
2. 自定义IP限流逻辑(更灵活)
如果需要更精细的控制,可基于Django缓存实现IP维度的请求计数,完全避免第三方库的异常问题:
from django.core.cache import cache from django.http import HttpResponseTooManyRequests from django.shortcuts import render def home_page(request): # 获取客户端IP client_ip = request.META.get('REMOTE_ADDR') cache_key = f"rate_limit_{client_ip}" # 获取当前请求次数,默认0 request_count = cache.get(cache_key, 0) if request_count >= 5: return HttpResponseTooManyRequests("请求过于频繁,请稍后再试") # 更新缓存:计数+1,有效期10秒 cache.set(cache_key, request_count + 1, 10) user_id = request.session.get("user_id") authorized = user_id is not None return render(request, template_name="index.html", context={"authorize": authorized})
3. 进阶优化建议
- 前端配合添加请求间隔限制,减少无效请求到达后端
- 若有服务器权限,优先在Nginx层面配置IP限流,性能远优于Python代码层面的控制
- 针对持续恶意攻击的IP,可编写Django中间件实现IP黑名单机制,直接拦截请求
内容的提问来源于stack exchange,提问作者Can't get my programs to work
相关产品推荐
相关产品推荐

