如何防护客户端JS错误上报API端点防垃圾攻击?是否必要?
首先得明确:即使不公开这个端点,防护依然有必要。恶意爬虫、自动化扫描工具很可能会扫到你的API路径,批量发送垃圾请求不仅会占用服务器资源、填满错误日志存储,甚至可能注入恶意数据干扰分析。不过不用搞太复杂的方案,以下几个符合你需求(不存客户端标识、无需验证码/邮件验证)的策略可以组合使用:
一、优雅通用的防护策略
1. 客户端隐式签名验证
在你的React应用中嵌入一个只有服务端和客户端知晓的密钥(比如通过环境变量注入的REACT_APP_ERROR_REPORT_SECRET,虽然SPA能被反编译,但能挡住绝大多数非针对性的攻击)。上报错误时,客户端做两件事:
- 给请求加上一个短有效期的时间戳(比如5分钟内)
- 用HMAC-SHA256对
错误内容+时间戳进行签名,把签名和时间戳放在请求头里(比如X-Error-Signature和X-Error-Timestamp)
服务端收到请求时:
- 先验证时间戳是否在有效期内,防止重放攻击
- 用相同的密钥重新计算签名,和请求头里的签名比对
- 验证通过再处理错误数据,否则直接丢弃
这种方式不用存储任何客户端标识,只是做一次性的签名验证,门槛足够挡住批量垃圾请求。
2. 请求上下文轻量校验
添加几个无状态的校验规则,不用存数据:
- 检查
Referer头是否属于你的应用域名(虽然能伪造,但大部分自动化工具不会特意去做,能过滤掉很多随机扫描的请求) - 校验
User-Agent是否来自常见浏览器(排除curl、Postman这类工具的UA,不过要留一定余地,比如允许未知UA,避免误杀特殊浏览器的请求)
3. 动态上报路径
不要用固定的/errors作为端点,改成动态生成的路径:
- 客户端启动时,先向服务端请求一个临时的上报路径(比如
GET /api/error-report-path) - 服务端返回一个随机生成的短路径(比如
/api/report-error/xyz789),并在内存中维护一个有效路径列表,每隔1小时更新失效旧路径 - 客户端用这个临时路径上报错误,服务端只处理当前有效的路径
这种方式即使有人扫到旧路径,也无法继续发送垃圾请求,而且不用存储任何客户端信息。
4. 静默式内容限流
针对错误内容做轻量的限流,不用基于IP:
- 对错误内容做哈希,短时间内(比如1分钟)收到相同哈希的请求超过N次,就暂时丢弃
- 用内存中的计数器(比如Guava的
RateLimiter或者自定义的ConcurrentHashMap)来记录,计数器定期过期,不用持久化
这种方式能挡住批量发送相同垃圾数据的请求,同时不存储任何客户端标识。
二、仅验证数据结构是否足够?
不够。恶意者很容易构造符合数据结构的垃圾数据(比如随机生成错误栈、错误信息),批量发送后依然会占用你的存储和服务器资源。但如果结合上面的1-2个轻量策略(比如签名验证+Referer校验),就能大幅降低垃圾请求的数量,足够应对绝大多数场景。
三、防护操作有没有必要?
有必要,但不用过度防护。毕竟错误上报端点的攻击价值不高,很少会有针对性的攻击,只要挡住自动化的垃圾请求就足够了。上面的策略都是轻量、无状态的,不会增加太多开发成本,却能避免后续的资源浪费和日志污染。
内容的提问来源于stack exchange,提问作者bkis

