客户端-服务器架构:如何确保客户端请求的合法性与安全性?
核心原则
服务器必须完全不信任客户端传来的任何参数,所有权限判断、数据合法性校验都在服务器端完成,这是解决这类问题的根本。
具体解决方法
绑定用户与可访问Chest的权限关系
服务器端维护每个用户的可交互Chest列表:比如基于用户当前游戏位置(是否在Chest的可交互范围内)、Chest的归属权(是否为用户所有)、场景关联(用户当前所在场景的Chest)等。当客户端发送FetchFromChest(chestID)请求时,服务器先校验该用户是否有权限访问这个chestID,无权限直接返回错误。
举个实际例子:用户点击游戏内的Chest后,客户端传过来的chestID,服务器先查用户当前坐标是否在该Chest的交互半径内,不在就拒绝请求,不管客户端传的ID是什么。避免暴露真实Chest ID给客户端
给客户端返回的是临时会话ID,而非数据库中的真实chestID。服务器维护一张临时ID与真实ID的映射表,映射关系仅在用户处于该Chest可交互范围内有效(用户离开后失效)。客户端请求时传临时ID,服务器先转成真实ID,再做权限校验。就算客户端篡改临时ID,没有对应的映射关系和权限,也拿不到有效数据。请求签名验证(防篡改增强)
给每个用户会话分配唯一的session_key,客户端发起请求时,除了chestID,还要带上用chestID + session_key + 时间戳通过哈希算法生成的签名。服务器收到请求后,用相同的参数重新计算签名并对比,不一致则拒绝请求。同时校验时间戳,防止重放攻击。
伪代码示例:// 客户端生成签名 string sign = MD5(chestID + session_key + timestamp); // 服务器验证签名 string expectedSign = MD5(receivedChestID + userSessionKey + receivedTimestamp); if (sign != expectedSign || timestamp过期) { 拒绝请求; }请求上下文与频率限制
服务器记录用户的请求上下文:比如短时间内频繁请求不同Chest、请求的Chest不在用户当前场景等异常行为,直接触发限流或拒绝。比如用户在场景A,突然请求场景B的Chest,服务器直接拒绝,因为用户不可能瞬间跨场景交互。
关于请求篡改的疑问
客户端确实可以篡改请求参数,但只要服务器不依赖客户端的参数做决策,所有校验逻辑都在服务器端基于自身存储的用户、Chest数据完成,客户端的篡改就不会生效。服务器只认自己的权限规则,不管客户端传什么非法参数,都无法绕过校验拿到不属于用户的数据。
内容的提问来源于stack exchange,提问作者thePOOOISE

