You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django与Django Rest Framework开发的HTTP API中添加IP白名单?

Django + DRF 接口IP白名单限制实现方案

以下是两种常用实现方式,可根据实际需求选择:


方案一:自定义Django中间件(全局生效,适合所有接口都需校验的场景)

这种方式在请求进入视图层之前就完成IP校验,性能损耗最低,所有HTTP请求都会触发校验。

实现步骤:

  1. 在settings.py中添加白名单配置,支持单个IP和CIDR网段:
# settings.py
ALLOWED_IP_WHITELIST = [
    "127.0.0.1",
    "192.168.1.0/24",
    # 按需添加你的IP
]
  1. 在你的APP目录下新建ip_middleware.py,写入以下逻辑:
# ip_middleware.py
from ipaddress import ip_address, ip_network
from django.conf import settings
from django.http import HttpResponseForbidden

class IPWhitelistMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # 提前把网段转换成ip_network对象,避免每次请求都重复转换提升性能
        self.allowed_ips = []
        self.allowed_networks = []
        for item in settings.ALLOWED_IP_WHITELIST:
            if "/" in item:
                self.allowed_networks.append(ip_network(item, strict=False))
            else:
                self.allowed_ips.append(ip_address(item))
    
    def __call__(self, request):
        # 获取客户端真实IP,有反向代理的情况取X-Forwarded-For头
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            client_ip = ip_address(x_forwarded_for.split(',')[0].strip())
        else:
            client_ip = ip_address(request.META.get('REMOTE_ADDR'))
        
        # 校验IP是否在白名单
        ip_allowed = client_ip in self.allowed_ips
        if not ip_allowed:
            for network in self.allowed_networks:
                if client_ip in network:
                    ip_allowed = True
                    break
        
        if not ip_allowed:
            return HttpResponseForbidden("Access denied")
        
        response = self.get_response(request)
        return response
  1. 在settings.py的MIDDLEWARE列表中添加该中间件,放在列表靠前的位置,优先执行校验:
# settings.py
MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    # 新增的IP校验中间件,放在安全中间件之后即可
    "你的APP名称.ip_middleware.IPWhitelistMiddleware",
    # 其他原有中间件
    ...
]

方案二:DRF自定义权限类(仅对DRF接口生效,可灵活控制作用范围)

如果只需要限制DRF的API接口,或者只需要给部分接口加IP限制,用这种方案更灵活。

实现步骤:

  1. 白名单配置和上面一致,先加在settings.py中
  2. 在APP目录下新建permissions.py,写入自定义权限类:
# permissions.py
from ipaddress import ip_address, ip_network
from django.conf import settings
from rest_framework.permissions import BasePermission

class IPWhitelistPermission(BasePermission):
    message = "Access denied"
    # 提前转换白名单格式提升性能
    allowed_ips = []
    allowed_networks = []
    for item in settings.ALLOWED_IP_WHITELIST:
        if "/" in item:
            allowed_networks.append(ip_network(item, strict=False))
        else:
            allowed_ips.append(ip_address(item))
    
    def has_permission(self, request, view):
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            client_ip = ip_address(x_forwarded_for.split(',')[0].strip())
        else:
            client_ip = ip_address(request.META.get('REMOTE_ADDR'))
        
        if client_ip in self.allowed_ips:
            return True
        for network in self.allowed_networks:
            if client_ip in network:
                return True
        return False
  1. 启用方式二选一:
  • 全局生效:所有DRF接口都开启IP校验,在settings.py中添加配置
# settings.py
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        "你的APP名称.permissions.IPWhitelistPermission",
        # 其他原有权限类
        ...
    ]
}
  • 单个视图生效:只给指定接口加IP校验,在对应的视图类中添加配置
from rest_framework.views import APIView
from 你的APP名称.permissions import IPWhitelistPermission

class YourAPIView(APIView):
    permission_classes = [IPWhitelistPermission]
    # 后续视图逻辑
    ...

注意事项

  • 如果你使用了Nginx、CDN等反向代理服务,必须配置代理服务传递真实客户端IP,以Nginx为例,需要在配置中添加proxy_set_header X-Forwarded-For $remote_addr;,否则会获取到代理服务器的IP导致校验失效
  • 生产环境建议将白名单配置在环境变量或数据库中,避免修改白名单需要重启服务
  • 拦截请求返回的错误信息不要暴露IP校验的细节,降低被攻击的风险

内容的提问来源于stack exchange,提问作者Pranav Pateriya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 23:36:07