缓存穿透导致接口频繁被刷,该怎么防?

萌新.雨婷 阅读 3

我们有个商品详情页,用户输入不存在的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]);

是不是应该把空结果也缓存一段时间?但又怕占太多内存,有没有更优雅的做法?

我来解答 赞 3 收藏
二维码
手机扫码查看
1 条解答
UP主~春芳
你这个情况典型的缓存穿透问题。我建议几个关键改进点:

首先必须把空结果也缓存起来,不然攻击者用随机ID就能一直穿透到DB。给空结果设置短一点的TTL,比如5分钟,这样既能缓解攻击又不会占用太多内存。

前端可以这样改:
// 缓存空结果时用特殊标记
const cached = localStorage.getItem(product_${id});
if (cached) {
if (cached === 'NULL') return setData(null); // 空结果处理
return setData(JSON.parse(cached));
}

const res = await fetch(/api/product/${id});
const data = await res.json();

if (data?.id) {
localStorage.setItem(product_${id}, JSON.stringify(data));
} else {
// 空结果缓存5分钟
localStorage.setItem(product_${id}, 'NULL', { expires: 300 });
}
setData(data);


后端更关键,必须做这些防护:
1. 加布隆过滤器,快速判断ID是否有效
2. 对频繁请求的IP做限流
3. 商品ID要做格式校验,防止随机字符串攻击

安全提醒:前端缓存只是辅助,主要防护要放在后端。攻击者完全可以绕过前端直接调API,所以后端必须实现布隆过滤和限流。

另外吐槽下,你们这个产品详情页居然不做ID有效性校验就直接查库,这简直是给黑客开绿灯啊...(来自一个凌晨三点还在处理类似问题的苦逼开发)
点赞
2026-03-05 19:00