基于Azure SQL的用户管理网站:Fetch调用Delete User接口无法传递ID的问题及处理方案
问题分析与优化方案
我来帮你梳理下这个问题的解决方案,同时给你几个更规范和安全的优化方向~
你的核心问题是最初的Fetch请求没有携带用户ID,导致后端接口无法定位要删除的目标;你找到的URL查询参数方式是可行的,但我们可以从API语义规范和安全性两个维度做优化。
一、正确传递ID的几种方式
1. URL路径参数(RESTful风格推荐)
这是RESTful API的标准写法,把ID放在URL路径里,语义更清晰,比如/deleteUser/:id:
后端修改(假设用Express框架)
// 先修改路由定义 app.delete('/deleteUser/:id', deleteUser); // 控制器中获取ID的方式改为从params取 const deleteUser = (req, res) => { const { id } = req.params; // 提前校验ID是否存在 if (!id) { return res.json("Please provide an ID"); } sql.connect(config, function (err) { if (err) { console.log(err); return res.status(500).json("Database connection error"); } var request = new sql.Request(); // 后续数据库操作... }); };
前端Fetch调用
<script> document.getElementById('deleteUserBtn').addEventListener('submit', (e) => { e.preventDefault(); const id = document.getElementById('userId').textContent; fetch(`http://localhost:3000/deleteUser/${id}`, { method:'DELETE', headers: { "Content-Type": "application/json", } }) .then(response => response.json()) .then(data => console.log(data)) .catch(e => console.log(e)); }); </script>
2. 请求体传递(适合复杂参数场景)
虽然DELETE请求通常不强制带body,但如果后续需要传递更多参数,这种方式也可行:
后端修改
const deleteUser = (req, res) => { const { id } = req.body; if (!id) { return res.json("Please provide an ID"); } // 后续数据库操作... };
前端Fetch调用
<script> document.getElementById('deleteUserBtn').addEventListener('submit', (e) => { e.preventDefault(); const id = document.getElementById('userId').textContent; fetch('http://localhost:3000/deleteUser', { method:'DELETE', headers: { "Content-Type": "application/json", }, body: JSON.stringify({ id }) }) .then(response => response.json()) .then(data => console.log(data)) .catch(e => console.log(e)); }); </script>
3. 保留你的URL查询参数方式(优化校验逻辑)
你当前的写法是可以工作的,但要调整参数校验的顺序——现在的代码会先执行SQL再判断ID是否为空,容易引发错误,应该提前校验:
const deleteUser = (req, res) => { const { id } = req.query; // 先校验ID,再连接数据库 if (!id) { return res.json("Please provide an ID"); } sql.connect(config, function (err) { if (err) { console.log(err); return res.status(500).json("Database connection error"); } var request = new sql.Request(); // 后续数据库操作... }); };
二、关键安全优化:防止SQL注入
你当前的代码直接把id拼进SQL字符串,这是严重的SQL注入风险!比如攻击者传入id=' OR '1'='1,会直接清空整个users表。必须改用参数化查询:
const deleteUser = (req, res) => { const { id } = req.params; if (!id) { return res.json("Please provide an ID"); } sql.connect(config, function (err) { if (err) { console.log(err); return res.status(500).json("Database connection error"); } var request = new sql.Request(); // 使用参数化查询,根据User_ID字段类型调整(比如sql.Int如果是数字ID) request.input('userId', sql.VarChar, id); request.query( `DELETE FROM users where User_ID = @userId`, function (err, recordset) { if (err) { console.log(err); return res.status(400).json("Failed to delete user"); } res.json(`User with ID: ${id} has been deleted!`); } ); }); };
三、前端体验优化
可以添加加载状态和成功后的DOM操作,提升用户体验:
<script> document.getElementById('deleteUserBtn').addEventListener('submit', async (e) => { e.preventDefault(); const btn = e.target; const id = document.getElementById('userId').textContent; // 添加加载状态 btn.disabled = true; btn.textContent = 'Deleting...'; try { const response = await fetch(`http://localhost:3000/deleteUser/${id}`, { method:'DELETE', headers: { "Content-Type": "application/json", } }); const data = await response.json(); console.log(data); // 删除页面上对应用户的DOM元素 document.getElementById(`user-${id}`)?.remove(); } catch (e) { console.log(e); } finally { // 恢复按钮状态 btn.textContent = 'Delete User'; btn.disabled = false; } }); </script>
内容的提问来源于stack exchange,提问作者Sejrskild
相关产品推荐
相关产品推荐

