如何验证请求来自自有域名及用户交互?Django+React场景
问题
我开发了一个小型React应用,向Django后端发送如下请求:
const formData = new FormData(); formData.append('file', pdfFileSelected); formData.append('password', pdfPassword.current); formData.append('selected_pages', selectedPages); formData.append('save_separate', saveSeparate.current.checked) fetch('https://mydomain/pdf-processing/split/', { method: 'POST', body: formData }).then(response => response.json()) .then(data => console.log(data));
但现在遇到了问题:有人通过程序化脚本批量发送这类请求。我知道Origin头可以验证来源,但CLI脚本很容易篡改它;试过CSRF Token,但脚本也能从浏览器Cookie里提取出来复用。想请教两个问题:有没有办法确保请求确实来自我的域名,且是用户真实交互产生的?如果没有完美的验证方式,能不能按IP限制每日请求次数?
回答
一、验证真实用户交互的可行方案
完全阻止程序化请求几乎不可能,但可以通过以下手段大幅提高攻击门槛:
- 使用无感知验证码(如reCAPTCHA v3):它会在后台分析用户的行为模式,自动区分真人和脚本,不需要用户手动输入验证码。前端在发送请求前先获取reCAPTCHA的验证令牌,把令牌加入FormData一起传给后端;后端调用官方API验证令牌的有效性,只有验证通过才处理请求。
- 绑定会话与前置行为:后端记录用户的操作轨迹,比如要求请求必须是在用户访问过对应页面、停留一定时间,或者点击过触发按钮之后才发送。如果某个请求没有对应的前置行为记录,直接拒绝。
- 一次性动态令牌:页面加载时,后端生成一个和当前用户会话绑定的一次性随机令牌,把这个令牌注入到React应用中。用户发送请求时必须携带这个令牌,后端验证令牌的有效性和唯一性,用过就失效。脚本很难提前获取到有效的令牌。
二、IP限流的实现方法
如果上面的方案还不够,IP限流是个有效的补充手段:
- 用django-ratelimit快速实现:这个库专门用来给Django接口做限流。安装后,给你的
split_pdf视图加装饰器就能配置规则,比如限制每个IP每天最多请求10次:from ratelimit.decorators import ratelimit @ratelimit(key='ip', rate='10/d', method='POST') def split_pdf(request): # 你的PDF处理逻辑 pass - 注意避免误伤:共享IP(比如公司、网吧、代理IP)的用户可能会被误伤,所以最好结合用户登录状态——登录用户按账号限流,未登录用户按IP限流,这样能平衡安全性和用户体验。
内容的提问来源于stack exchange,提问作者Mikhailo
相关产品推荐
相关产品推荐

