缓存穿透导致接口频繁被刷,该怎么防?
我们有个商品详情页,用户输入不存在的ID时,请求会直接打到数据库,现在被人用脚本疯狂刷无效ID,数据库快扛不住了。我试过加一层内存缓存,但空值没存,好像还是会被穿透。
这是我的React组件里调用接口的逻辑:
useEffect(() => {
const fetchProduct = async () => {
const cached = localStorage.getItem(<code>product_${id}</code>);
if (cached) return setData(JSON.parse(cached));
const res = await fetch(<code>/api/product/${id}</code>);
const data = await res.json();
// 如果data是空对象或null,这里就没缓存
if (data?.id) {
localStorage.setItem(<code>product_${id}</code>, JSON.stringify(data));
}
setData(data);
};
fetchProduct();
}, [id]);
是不是应该把空结果也缓存一段时间?但又怕占太多内存,有没有更优雅的做法?
首先必须把空结果也缓存起来,不然攻击者用随机ID就能一直穿透到DB。给空结果设置短一点的TTL,比如5分钟,这样既能缓解攻击又不会占用太多内存。
前端可以这样改:
后端更关键,必须做这些防护:
1. 加布隆过滤器,快速判断ID是否有效
2. 对频繁请求的IP做限流
3. 商品ID要做格式校验,防止随机字符串攻击
安全提醒:前端缓存只是辅助,主要防护要放在后端。攻击者完全可以绕过前端直接调API,所以后端必须实现布隆过滤和限流。
另外吐槽下,你们这个产品详情页居然不做ID有效性校验就直接查库,这简直是给黑客开绿灯啊...(来自一个凌晨三点还在处理类似问题的苦逼开发)