如何判断Lua表是否由apple_new函数创建,规避伪造实例?
不用元表区分Apple实例的解决方案
好问题!不用元表来识别apple_new创建的实例,核心是要利用Lua闭包的私有作用域特性——创建一个只有apple_new和is_apple能访问的唯一标记,伪造的实例无法获取这个标记的引用,自然无法模仿。
下面是两种可行的方案:
方案一:私有标记表作为隐藏键
这个方案给每个Apple实例添加一个外部无法访问的隐藏字段,通过检查这个字段来验证身份:
-- Apple.lua -- 定义一个私有标记,只有当前文件内的函数能访问 local apple_marker = {} function apple_new() local self = { } -- 给实例添加隐藏标记:外部不知道apple_marker的引用,无法伪造 self[apple_marker] = true local size = 1 function self.grow() size = size + 1 end function self.size() return size end return self end function is_apple(table) if type(table) ~= "table" then return false end -- 验证逻辑:必须是表,有grow/size方法,且包含私有标记 return table[apple_marker] == true and type(table.grow) == "function" and type(table.size) == "function" end
为什么伪造的实例无法绕过?
伪造的表比如local y = {size = function() end, grow = function() end}根本无法添加self[apple_marker] = true这行代码——因为apple_marker是Apple.lua内的局部变量,外部完全无法获取它的引用,自然无法模仿这个隐藏标记。
方案二:方法的秘密验证接口
这个方案通过给size方法添加一个只有内部知道的验证参数,让真正的实例能返回私有标记,伪造的实例做不到:
-- Apple.lua local apple_marker = {} function apple_new() local self = { } local size = 1 function self.grow() size = size + 1 end function self.size(verify) -- 如果传入约定的验证请求,返回私有标记 if verify == "verify_apple_instance" then return apple_marker end -- 正常调用返回size值 return size end return self end function is_apple(table) if type(table) ~= "table" then return false end if type(table.grow) ~= "function" or type(table.size) ~= "function" then return false end -- 调用size方法的验证接口,检查是否返回私有标记 local verify_result = table.size("verify_apple_instance") return verify_result == apple_marker end
优势
这个方案不会给实例表添加额外字段,更隐蔽。伪造的实例就算模仿了size方法的验证分支,返回的也只能是自己创建的新表(比如return {}),而Lua中只有同一个表引用才会相等,所以永远无法匹配apple_marker。
总结
两种方案都完全不需要元表,核心都是利用Lua的局部变量私有性和表的引用相等性,让真正的实例拥有伪造者无法复制的“身份标识”。如果追求简洁,方案一更合适;如果希望更隐蔽,方案二是更好的选择。
内容的提问来源于stack exchange,提问作者Hatefiend
相关产品推荐
相关产品推荐

