很多人写网页时用fetch发请求,觉得只是拿点ref="/tag/426/" style="color:#643D3D;font-weight:bold;">数据,没什么大不了。可你有没有想过,随手写的几行代码,可能正把用户信息往外送?
一个简单的fetch,也可能埋雷
比如你在做个小区公告板页面,想从服务器拉最新通知:
fetch('/api/notice')
.then(response => response.json())
.then(data => console.log(data));
看起来没问题,但如果你的网站被插入了恶意脚本,或者接口没做权限控制,攻击者就能用同样的方式,悄悄读取用户的私人消息、门禁记录,甚至住户名单。
别默认带上凭据
有些开发者为了“省事”,在fetch里加上 credentials: 'include',以为能自动登录:
fetch('https://api.example.com/user', {
method: 'GET',
credentials: 'include'
})
这就像把家门钥匙挂在门外的信箱上。一旦第三方脚本运行,它就能拿着你的身份去访问所有接口。尤其在公共WiFi下,风险更大。
只信得过的域名才连
有人图方便,直接用变量拼URL:
const domain = localStorage.getItem('api_host');
fetch(`${domain}/data`)
如果攻击者篡改了这个存储值,你的页面就会把数据发到他的服务器上。正确的做法是固定域名,或者在配置里白名单限定。
加个超时,别让请求卡住
网络环境复杂,特别是手机信号不稳时,fetch默认不会超时。长时间挂起的请求可能被利用,拖慢页面甚至触发重试攻击。
可以用AbortController控制时间:
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);
fetch('/api/safe-check', { signal: controller.signal })
.then(r => r.json())
.catch(e => {
if (e.name === 'AbortError') {
console.warn('请求超时');
}
});
这样最多等5秒,避免陷入无限等待。
敏感操作不用GET
有人用fetch删数据还用GET:
fetch('/delete-camera?room=301')
这太危险了。浏览器、代理、日志都可能记录URL,别人翻翻历史就看到你删了哪个房间的监控。该用POST或DELETE,参数走请求体。
检查返回类型,防中间人
公共网络下,响应内容可能被替换。你以为拿到的是JSON,其实是个钓鱼页面。
加一步类型判断:
fetch('/api/status')
.then(response => {
if (!response.ok) throw new Error('请求失败');
const contentType = response.headers.get('content-type');
if (!contentType || !contentType.includes('application/json')) {
throw new Error('非法响应类型');
}
return response.json();
})
多这一层,至少能挡住明目张胆的篡改。
写代码不是越快越好,而是让每个请求都可控、可查、可信。毕竟,你处理的不只是数据,还有别人的生活安全。