在DRF框架中,当使用Nginx作为反向代理时,由于请求被代理到127.0.0.1,Python项目无法直接获取客户端的真实IP地址,这会导致DRF的匿名用户限流功能(基于IP识别)失效。以下是解决这一问题的详细方案:
1. 配置Nginx传递真实IP设置X-Forwarded-For头:在Nginx配置中,确保将客户端的真实IP通过X-Forwarded-For头传递给后端服务。例如:
location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_pass http://127.0.0.1:8000;
}$proxy_add_x_forwarded_for会自动追加客户端IP和代理服务器IP(格式如client_ip, proxy1_ip, proxy2_ip)。
信任代理层数:如果Nginx前还有其他代理(如CDN、负载均衡器),需在DRF中配置NUM_PROXIES,明确代理层数。例如:
# settings.pyNUM_PROXIES = 2 # 根据实际代理数量调整
2. 调整DRF的IP识别逻辑- 覆盖get_ident方法:自定义限流类,重写get_ident方法以正确解析X-Forwarded-For头。例如:from rest_framework.throttling import AnonRateThrottleclass CustomAnonThrottle(AnonRateThrottle): def get_ident(self, request): xff = request.META.get('HTTP_X_FORWARDED_FOR') remote_addr = request.META.get('REMOTE_ADDR') if xff: # 提取最左侧的客户端IP(假设NUM_PROXIES已配置) addrs = [ip.strip() for ip in xff.split(',')] return addrs[-min(settings.NUM_PROXIES, len(addrs))] return remote_addr
- 全局替换限流类:在DRF配置中指定自定义限流类:# settings.pyREST_FRAMEWORK = { 'DEFAULT_THROTTLE_CLASSES': [ 'path.to.CustomAnonThrottle', ],}
3. 验证配置- 检查Nginx日志:确保Nginx正确传递了X-Forwarded-For头,日志中应包含类似:"X-Forwarded-For: 203.0.113.42, 198.51.100.10"
- 测试DRF接口:通过工具(如Postman)模拟请求,检查DRF是否正确识别客户端IP(而非127.0.0.1)。
4. 其他注意事项- 安全性:确保仅信任已知代理的X-Forwarded-For头,避免伪造IP。可通过Nginx配置限制可信代理:set_real_ip_from 192.168.1.0/24; # 信任的代理IP段real_ip_header X-Forwarded-For;
- 多代理场景:如果存在多级代理(如CDN → Nginx → DRF),需在NUM_PROXIES中指定正确的代理层数,确保提取到客户端真实IP。
5. 备选方案- 使用会话或Token:若IP限制不可靠,可改用会话或Token标识匿名用户(需权衡安全性与实现复杂度)。
通过以上步骤,DRF可以正确识别通过Nginx代理的客户端IP,从而恢复匿名用户限流功能。核心在于确保Nginx传递真实IP,并在DRF中正确解析代理头信息。