Django REST Framework如何仅允许指定IP列表访问API端点?
基于IP地址限制API端点访问的实现方案
一、反向代理层配置(以Nginx为例)
这是生产环境最常用的方案,在流量入口层处理,不占用应用服务器资源,配置灵活。直接针对不同API端点单独设置IP白名单:
# 限制只有指定IP/网段能访问私有API location /api/private { # 允许单个IP allow 192.168.1.100; # 允许整个网段 allow 10.0.0.0/24; # 兜底拒绝所有其他IP deny all; # 常规反向代理配置 proxy_pass http://your-api-backend; proxy_set_header Host $host; # 传递真实客户端IP给后端(可选,方便日志排查) proxy_set_header X-Forwarded-For $remote_addr; } # 公开API不做IP限制 location /api/public { proxy_pass http://your-api-backend; proxy_set_header Host $host; }
二、应用层直接实现(以Python Flask为例)
如果不想依赖反向代理,可以在应用代码里通过装饰器实现细粒度IP控制:
先写一个IP校验装饰器:
from flask import request, abort import ipaddress def allow_only_ips(allowed_ranges): def decorator(view_func): def wrapped_view(*args, **kwargs): # 优先取反向代理传递的真实IP(如果有) client_ip = request.headers.get('X-Forwarded-For', request.remote_addr).split(',')[0].strip() try: client_ip_obj = ipaddress.ip_address(client_ip) # 检查IP是否在允许的网段内 for ip_range in allowed_ranges: if client_ip_obj in ipaddress.ip_network(ip_range, strict=False): return view_func(*args, **kwargs) except ValueError: # 无效IP格式直接拒绝 abort(403) # 不在白名单内返回403 abort(403, description="IP not authorized") return wrapped_view return decorator
将装饰器应用到需要限制的端点:
@app.route('/api/private') @allow_only_ips(allowed_ranges=['192.168.1.100/32', '10.0.0.0/24']) def private_api(): return {"data": "This is restricted content"} # 公开端点不需要装饰器 @app.route('/api/public') def public_api(): return {"data": "This is public content"}
三、API网关配置
如果用云服务商的API网关(比如AWS API Gateway、阿里云API网关),可直接在网关路由规则里配置IP访问控制,无需修改应用代码:
以AWS API Gateway为例,给指定路由添加资源策略:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "execute-api:Invoke", "Resource": "arn:aws:execute-api:us-east-1:1234567890:abc123/dev/GET/api/private", "Condition": { "IpAddress": { "aws:SourceIp": ["192.168.1.100/32", "10.0.0.0/24"] } } } ] }
该策略会限制只有指定IP/网段能访问目标路由,其他路由可单独配置或保持默认开放。
关键注意事项
- 获取真实IP:如果应用前有CDN、反向代理,一定要从
X-Forwarded-For或X-Real-IP头提取客户端真实IP,否则会把代理服务器IP当成客户端IP,导致限制失效。 - 网段管理:尽量用CIDR格式管理IP段,比单个IP更易维护,比如
10.0.0.0/24代表10.0.0.1到10.0.0.254的所有IP。 - 测试验证:配置完成后,用白名单外IP请求私有端点,确认返回403;用白名单内IP请求,确认能正常访问。
内容的提问来源于stack exchange,提问作者Sid
相关产品推荐
相关产品推荐

