Node.js中通过Referer头判断API调用来源的代码安全性问询
咱们直接针对你的疑问逐一分析:
1. 这段代码安全吗?
不安全,因为存在链式调用的潜在崩溃风险。你写的req.headers && req.headers.referer.split('/')[2]只判断了req.headers是否存在,但没检查req.headers.referer是否存在。如果referer头不存在,req.headers.referer就是undefined,调用.split('/')时会直接抛出TypeError: Cannot read properties of undefined (reading 'split'),导致请求处理失败,服务器返回500错误。
而且还有个隐藏问题:即使referer存在,它的格式也不一定符合预期(比如有些referer可能是相对路径,或者格式不标准),直接取split('/')[2]可能拿到undefined或者错误的值。
2. 哪些场景下headers会不存在?
严格来说,HTTP协议要求请求必须包含headers,但在实际场景中,你更需要担心的是**referer头不存在**的情况,常见场景包括:
- 用户直接在浏览器地址栏输入你的API地址访问
- 浏览器开启隐私模式时,部分浏览器会自动屏蔽
Referer头 - 客户端(比如POSTMAN、curl)主动不设置
Referer头 - 跨域请求中,浏览器可能限制
Referer的发送(比如只发送域名,或者完全不发) - 代理服务器、防火墙或浏览器插件主动移除了
Referer头 - 一些极简的自定义HTTP客户端,没有添加
Referer头的逻辑
至于req.headers本身不存在的情况,在Express、Koa这类主流Node.js Web框架里几乎不会出现,因为框架会自动解析请求头并挂载到req.headers上,但如果是你自己手动处理原始HTTP请求(比如用http模块直接写服务),极端情况下可能遇到没有headers的请求,但这种情况非常罕见。
3. 用POSTMAN调用且不设置该请求头,代码会出问题吗?
肯定会出问题!当你在POSTMAN里不设置Referer头时,请求不会携带这个字段,req.headers.referer就是undefined。此时执行.split('/')就会触发上面提到的TypeError,导致你的请求处理逻辑崩溃,服务器返回500内部错误。
改进方案
给你两种更安全的写法:
方案一:使用可选链操作符(ES2020+支持)
const mySite = req.headers?.referer?.split('/')[2];
这种写法会在每一步遇到undefined或null时直接返回undefined,不会抛出错误。
方案二:更严谨的条件判断(兼容旧环境)
let mySite = null; // 先检查headers和referer是否存在,再判断分割后的数组长度 if (req.headers && req.headers.referer) { const urlParts = req.headers.referer.split('/'); if (urlParts.length >= 3) { mySite = urlParts[2]; } }
最后还要提醒一句:Referer头是可以被伪造的,如果你想用它来验证请求来源的合法性,不能只依赖这个头,最好配合API密钥、JWT Token或者其他更可靠的验证方式。
内容的提问来源于stack exchange,提问作者user9728810

