如何阻止用户通过手动输入URL参数访问Express应用的指定路由
Express应用限制路由仅可通过按钮点击访问的实现方案
1. 核心改造:将GET请求替换为POST请求
GET请求的参数直接暴露在URL中,天然支持地址栏输入访问,替换为POST请求后参数存放在请求体中,用户无法通过地址栏输入URL触发POST请求,是成本最低的基础防护手段。
修改后前端请求代码:
export.onclick = function() { let index1 = dropdown1.value; let index2 = dropdown2.value; fetch('/export-doc', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ index1, index2 }) }) // 原有转blob对象、下载的逻辑保持不变 }
修改后后端路由代码:
app.post('/export-doc', function (req, res) { const { index1, index2 } = req.body; // 原有调用函数生成文档、返回文档的逻辑保持不变 });
2. 增强防护:添加一次性访问令牌校验
仅改POST无法拦截刻意构造的POST请求,可通过令牌机制进一步限制访问权限:
- 服务端渲染页面时,生成一个有效期短(建议5分钟以内)、仅单次有效的随机令牌,存储在当前用户的session或redis中,同时将令牌注入到前端页面的隐藏标签或全局变量中
- 前端发起导出请求时,将令牌放入请求头中传递给后端
- 后端收到请求后首先校验令牌合法性,校验通过后立刻销毁旧令牌,生成新令牌更新到用户session中,避免令牌被复用
前端请求添加令牌示例(假设页面存在ID为exportToken的隐藏输入框存储令牌):
fetch('/export-doc', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Export-Token': document.getElementById('exportToken').value }, body: JSON.stringify({ index1, index2 }) })
后端令牌校验示例:
app.post('/export-doc', function (req, res) { const requestToken = req.get('X-Export-Token'); const validToken = req.session.exportToken; // 校验不通过直接返回403 if (!requestToken || requestToken !== validToken) { return res.status(403).send('非法访问'); } // 校验通过后立即更新令牌,作废旧令牌 req.session.exportToken = generateRandomToken(); // 后续处理生成文档的业务逻辑 });
3. 附加校验规则进一步提升安全性
- 校验请求的
X-Requested-With请求头是否为XMLHttpRequest,地址栏直接发起的请求不会携带该标识,可直接拦截绝大部分手动输入访问的请求 - 校验请求
Referer头是否属于当前站点域名,拦截外站发起的非法调用 - 针对单个用户添加请求频率限制,避免暴力遍历参数的恶意请求
补充建议
即使做完以上防护,建议后端拿到index1和index2参数后,还是要补充校验两个参数对应的资源是否属于当前登录用户的权限范围,极端情况下就算令牌泄露,也能避免用户越权获取不属于自己的文档。
内容的提问来源于stack exchange,提问作者GriffsAccount
相关产品推荐
相关产品推荐

