
本文旨在指导开发者如何在用户接受好友请求后,将其信息添加到对方用户模式的 friends 数组中。文章将讨论避免前端篡改用户ID的措施,并通过 FriendRequest 模型查询好友列表,同时也会介绍如何在接受好友请求时更新用户模式,并强调使用事务以保证数据一致性的重要性。
在处理好友请求时,直接从前端获取发送者(sender)ID存在安全风险。恶意用户可以通过修改HTML来伪造发送者ID,从而导致数据不一致或潜在的安全问题。为了避免这种情况,应该从服务器端的会话或身份验证中间件中获取当前用户的ID。
例如,前端表单可以只包含接收者(receiver)的ID:
<form action="/requests" method="POST"> <input type="hidden" name="receiver" value="<%= receiverUserId %>" /> <button type="submit">Send Friend Request</button> </form>
在后端路由处理程序中,使用身份验证中间件提供的当前用户ID作为发送者:
router.post("/requests", (req, res) => {
const { receiver } = req.body;
FriendRequest.create({
sender: req.user._id, // 从身份验证中间件获取当前用户ID
receiver
}).then(() => {
res.status(204).send();
}).catch((error) => {
res.status(500).send("Error sending friend request");
});
});这里假设 req.user._id 包含了经过身份验证的用户的ID。你需要根据你使用的身份验证方法调整这部分代码。
一种更优雅的方式是避免在 User 模型中显式维护 friends 数组。相反,可以通过查询 FriendRequest 模型来获取好友列表。这种方法利用了 FriendRequest 模型中已经存在的 sender 和 status 字段。
例如,要获取当前用户的所有已接受的好友,可以使用以下查询:
FriendRequest
.find({sender: req.user._id, status: 'accepted'})
.then((listOfFriends)=>{
console.log(listOfFriends);
})
.catch((e)=>{
// handle error
})这种方法的优点是避免了数据冗余,并且在好友关系发生变化时,只需要更新 FriendRequest 模型即可。
如果仍然需要在 User 模型中显式维护 friends 数组,则需要在接受好友请求时更新这两个用户的 friends 数组。
router.post("/requests/:id/accept", async (req, res) => {
try {
const request = await FriendRequest.findById(req.params.id);
request.status = "accepted";
await request.save();
const currentUser = await User.findById(req.user._id); // 获取当前用户
const otherUser = await User.findById(request.receiver); // 获取接收者用户
currentUser.friends.push(request.receiver);
otherUser.friends.push(req.user._id);
await currentUser.save();
await otherUser.save();
res.redirect("/requests");
} catch (error) {
// 处理错误
console.error("Error accepting friend request:", error);
res.status(500).send("Error accepting friend request");
}
});注意事项:使用事务
在更新多个集合时,务必使用数据库事务来确保数据一致性。如果在更新 FriendRequest 模型后,更新 User 模型失败,则可能导致数据不一致。
以下是如何使用 Mongoose 事务的示例:
const mongoose = require('mongoose');
router.post("/requests/:id/accept", async (req, res) => {
const session = await mongoose.startSession();
session.startTransaction();
try {
const request = await FriendRequest.findById(req.params.id).session(session);
request.status = "accepted";
await request.save({ session });
const currentUser = await User.findById(req.user._id).session(session); // 获取当前用户
const otherUser = await User.findById(request.receiver).session(session); // 获取接收者用户
currentUser.friends.push(request.receiver);
otherUser.friends.push(req.user._id);
await currentUser.save({ session });
await otherUser.save({ session });
await session.commitTransaction();
session.endSession();
res.redirect("/requests");
} catch (error) {
await session.abortTransaction();
session.endSession();
// 处理错误
console.error("Error accepting friend request:", error);
res.status(500).send("Error accepting friend request");
}
});在这个示例中,mongoose.startSession() 创建一个新的会话,session.startTransaction() 启动事务。所有的数据库操作都通过 .session(session) 传递会话对象。如果所有操作都成功,则 session.commitTransaction() 提交事务;否则,session.abortTransaction() 回滚事务,撤销所有更改。
总结
在处理好友请求时,务必注意用户ID的安全性,并考虑使用 FriendRequest 模型查询好友列表,以避免数据冗余。如果需要在 User 模型中显式维护 friends 数组,则务必使用数据库事务来确保数据一致性。选择哪种方法取决于你的具体需求和对数据一致性的要求。
以上就是如何在用户模式中向好友数组添加用户的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号