MERN栈建议应用Delete请求403错误排查求助
排查Delete请求403错误:简易建议应用问题解决
开发带有认证功能和Context API状态管理的简易建议应用,已实现CRUD中的创建、读取、更新功能,但Delete请求始终返回403错误,控制台提示Request failed with status code 403。以下是相关代码及排查方案:
相关代码
Express后端Delete路由
router.delete("/bmi/delete/:id", async (req, res) => { const id = req.params.id; try { const suggest = await bmiCalc.findById(id); if (suggest.userId === req.body.userId) { await suggest.deleteOne(); res.status(200).json("Suggestion deleted"); } else { res.status(403).json("Not your Suggestion to delete"); } } catch (error) { res.status(500).json("Error from server"); } });
React前端Axios请求
const Home = () => { const { user } = useContext(AuthContext); const [data, setData] = useState([]); const handleSuggestion = async (e) => { e.preventDefault(); const fullDetail = { userId: user.users._id, bmiNumber: bmiNumber.current.value, country: country.current.value, messages: messages.current.value, }; const res = await axios.post( "http://localhost:5000/app/bmi/bmiform/create", fullDetail, ); setData([...data, res.data]); }; const reload = () => { window.location.reload(); }; useEffect(() => { const getSuggestion = async () => { const res = await axios.get( `http://localhost:5000/app/bmi/all/${user.users._id}`, ); setData(res.data); }; getSuggestion(); }, [user.users._id]); const handleDelete = async (id) => { try { await axios.delete(`http://localhost:5000/app/bmi/delete/${id}`, { data: { userId: user.users._id }, }); setData(data.filter((post) => post._id !== id)); } catch (err) { console.log(err.message); } }; };
Chakra UI按钮组件
<Flex w={"100%"} h={"60vh"} padding={"8px"} gap={"8px"} flexWrap={"wrap"} justifyContent={"flex-start"}> {data.map((item) => { return ( <Box key={item._id} width={["47%", "55%", "25%", "24%"]} height={["55%", "50%", "50%", "50%"]} bg={"#ffffff"} display={"flex"} flexDirection={"column"} borderRadius={7} gap={4} padding={5}> <Box w={"100%"} h={"5vh"} transition={"0.3s all"}> <p className='boxTitle'> BMI: {item.bmiNumber}</p> <p className='boxCountry'> {item.country}</p> </Box> <Box width={"100%"} height={"100%"} paddingTop={2}> <p className='boxMessage'> {item.messages}</p> </Box> <Flex width={"100%"} gap={1}> <Button bg={"#541db5"} type='submit' width='100%' outline='none' border='none' borderRadius={6} color='#ffffff' fontSize={20} fontWeight={600} marginBottom={4} padding={4}> edit </Button> {item.userId === user?.users._id && ( <Button onClick={() => handleDelete(item._id)} type='submit' width='100%' outline='none' border='none' borderRadius={6} color='#ffffff' fontSize={20} fontWeight={600} bg='#ef233c' marginBottom={4} padding={4}> <DeleteIcon /> </Button> )} </Flex> </Box> ); })} </Flex>
排查与解决方案
1. ObjectId与字符串类型不匹配
MongoDB存储的userId是ObjectId类型,而前端传递的user.users._id是字符串,直接用===比较会失败,导致返回403。
修改后端路由:
router.delete("/bmi/delete/:id", async (req, res) => { const id = req.params.id; try { const suggest = await bmiCalc.findById(id); // 转换为字符串统一类型后比较 if (suggest.userId.toString() === req.body.userId) { await suggest.deleteOne(); res.status(200).json("Suggestion deleted"); } else { // 打印日志确认匹配失败的具体值 console.log("User ID mismatch:", suggest.userId.toString(), req.body.userId); res.status(403).json("Not your Suggestion to delete"); } } catch (error) { console.error("Server error:", error); res.status(500).json("Error from server"); } });
也可以使用MongoDB ObjectId的equals方法:
if (suggest.userId.equals(req.body.userId)) { ... }
2. 前端条件渲染同步类型判断
前端按钮显示的条件也存在同样的类型问题,需要同步修改:
{item.userId.toString() === user?.users._id && ( <Button onClick={() => handleDelete(item._id)} type='submit' width='100%' outline='none' border='none' borderRadius={6} color='#ffffff' fontSize={20} fontWeight={600} bg='#ef233c' marginBottom={4} padding={4}> <DeleteIcon /> </Button> )}
3. 确认后端是否解析JSON Body
检查后端是否配置了express.json()中间件,否则req.body会为空,导致无法获取userId:
// 在app.js或server.js中添加 app.use(express.json());
4. 检查认证中间件拦截
确认Delete路由是否正确应用了认证中间件(比如JWT验证),避免因未携带认证信息被拦截返回403。
内容的提问来源于stack exchange,提问作者clemon ezeh
相关产品推荐
相关产品推荐

