如何限制Django网站仅允许浏览器发起请求,禁止终端/脚本请求
Django 仅允许浏览器发起请求的限制方案
要实现仅允许浏览器访问、拦截终端/脚本请求的需求,核心思路是通过验证请求的浏览器特征请求头过滤非浏览器请求。虽然无法100%拦截所有伪造请求,但能有效阻挡绝大多数普通脚本和直接终端请求。以下是具体实现步骤:
1. 编写自定义中间件
利用Django中间件全局拦截所有请求,添加浏览器验证逻辑:
from django.http import HttpResponseForbidden class BrowserOnlyMiddleware: def __init__(self, get_response): self.get_response = get_response # 定义常见浏览器的User-Agent标识(可按需扩展) self.allowed_browser_keywords = [ 'Mozilla', 'Chrome', 'Safari', 'Edge', 'Firefox', 'Opera', 'Brave', 'Vivaldi' ] def __call__(self, request): # 排除无需限制的路径(如后台、静态文件,可自定义) excluded_paths = ['/admin/', '/static/', '/media/'] if any(request.path.startswith(path) for path in excluded_paths): return self.get_response(request) # 获取请求的User-Agent头 user_agent = request.META.get('HTTP_USER_AGENT', '').lower() # 验证User-Agent是否包含浏览器标识 is_valid_browser = any(kw.lower() in user_agent for kw in self.allowed_browser_keywords) # 可选:开启Referer验证(仅当请求来自站内页面时启用,防止跨站脚本请求) # referer = request.META.get('HTTP_REFERER') # if referer and not referer.startswith(request.build_absolute_uri('/')): # is_valid_browser = False if not is_valid_browser: return HttpResponseForbidden("仅允许通过浏览器访问") response = self.get_response(request) return response
2. 配置中间件
将自定义中间件添加到项目settings.py的MIDDLEWARE列表中(建议放在CSRF中间件之后,保证逻辑顺序正确):
MIDDLEWARE = [ # 其他默认中间件... 'django.middleware.csrf.CsrfViewMiddleware', # 添加上方自定义中间件 'your_app_name.middleware.BrowserOnlyMiddleware', # 其他中间件... ]
3. 自定义调整规则
- 扩展浏览器标识:如需支持更多小众浏览器,直接在
allowed_browser_keywords列表中添加对应关键词即可。 - 调整排除路径:若有无需限制的API或页面,将其路径加入
excluded_paths,避免被拦截。 - 增强验证逻辑:结合Django默认的CSRF验证,脚本若不模拟浏览器的Cookie存储和CSRF流程,将无法通过验证。
4. 关于HTTP_X_FORWARDED_FOR的补充
你提到的request.META.get('HTTP_X_FORWARDED_FOR')用于获取IP,需注意:
- 若网站部署在反向代理(如Nginx)后,务必在
settings.py中配置SECURE_PROXY_SSL_HEADER和ALLOWED_HOSTS,确保获取真实用户IP,避免被伪造请求头误导。 - 即使限制了浏览器访问,仍需注意该头可能被伪造,建议结合反向代理层的IP验证进一步加固。
局限性说明
这种方法无法拦截专业爬虫或伪造请求头的脚本,但足以阻挡绝大多数普通终端请求和简单脚本,适配你的场景需求。
内容的提问来源于stack exchange,提问作者Roblox Boyeee
相关产品推荐
相关产品推荐

