"用 A 账号的会话操作 B 账号的物品""普通玩家调用管理接口"——越权操作是脚本攻击的直接变现手段。权限防线的设计原则:每一次敏感操作都在服务端独立校验,客户端传来的任何身份信息都只是待验证的声明。适用于:背包操作、交易、管理命令、后台接口。
每个敏感操作校验三件事:身份(会话 token 对应的账号是否有权操作目标对象)、归属(操作的目标资源是否属于该账号)、额度(操作量是否在规则允许范围内):
function BagService.takeItem(player, itemId, count)
assert(player and player.uid, "缺少会话身份")
local bag = loadBag(player.uid) -- 归属:只加载本人背包
local have = bag.count(itemId) or 0
if count > have then return false, "物品数量不足" end
if count > RULES.maxOnceTake then return false, "单次操作超限" end
...
end
归属校验的实现要点:目标资源永远按"本人 uid"查询加载,绝不接受客户端传入的"别人背包 id"之类参数。
管理类功能用三层权限模型:角色(玩家/GM/管理员)、资源类型(背包/邮件/配置)、动作(读/写/删)。权限表声明"哪个角色对哪类资源有哪些动作",校验走统一入口:
function checkPerm(role, resource, action)
local perms = PERM_TABLE[role]
return perms and perms[resource] and perms[resource][action]
end
未声明的组合一律拒绝(默认拒绝原则),新增功能先补权限表再开放接口。
全部敏感操作的调用写入审计日志(谁、何时、对什么、做了什么、结果),与 GM 日志同等级管理。上线前的渗透自查清单:用 A 的 token 请求 B 的资源、重复提交同一请求、传入越界的数量与 id、调用未在客户端出现过的命令号——四类测试全部拒绝才算达标。越权防线没有一劳永逸,每次新增功能都过一遍三要素校验,是唯一可持续的做法。
权限校验的单元测试覆盖三张表:角色权限表、资源类型表、组合拒绝表。每次新增管理功能时补对应的拒绝用例,权限模型的回归测试就从口头承诺变成了机器保障。