如何从全球范围内切断功能

How to cut off function from global scope

我有一个游戏想法,人们可以为他们的角色输入一些简单的指令,比如 player.goLeft() 或 player.attackInFront() 为此,我让人们将他们的代码输入到文本框,然后我将其解析为 eval()。这很有效,但它也允许人们通过输入 player.health = Infinity; 之类的东西来改变他们自己的角色对象。或类似的东西。我有一个允许人们使用的功能列表,但我不确定如何将其限制为仅使用它们。

我知道不让人们使用 eval 的全部意义在于避免意外的跨站点脚本,但我不确定还有什么方法可以做到这一点。如果您有任何建议,请发表评论。

我问了周围的一些人该怎么做,大多数人建议以某种方式改变范围(这是我无法弄清楚的事情)或向我的代码中的每个函数添加一些奇怪的参数,这些参数将被要求一个特定的字符串来执行任何功能,但这看起来很老套,而且由于我是在浏览器中使用 p5js 制作游戏,所以只需检查元素并查看密码是什么就很容易了。

基本上每个字符都有一个名为"instruction"的变量,它只是一个javascript的字符串。然后我通过执行 eval(playerList[i].instruction);

来执行游戏的每一帧

tl;dr,我怎样才能只允许执行特定功能而不允许执行任何其他功能?

编辑:我忘了说我还计划向玩家提供信息,以便人们可以编写适应这种情况的代码。例如,将有一个名为 vision 的参数,其中包含 vision.front 和 vision.left 等。这些变量只会说明在网格中它们周围是否有敌人、墙、花等。有人建议我只是用关键字替换一些函数,但这样会损害使用 if 语句并使其行为不同的想法。

编辑 2:很抱歉此 post 中缺少代码,但由于我的制作方式,一半的逻辑编写在服务器端,一半在客户端运行。它会有点大,老实说,我不确定我的代码的可读性如何,但到目前为止,我得到了很大的帮助,对此我深表感谢。谢谢大家的回答

请勿使用 eval() 将任意用户输入作为代码执行!没有办法允许您的代码 运行 一个函数但阻止 eval() 做同样的事情。

相反,您应该做的是制作玩家可以使用的命令映射,将它们映射到函数。这样,您 运行 基于地图查找的功能,但如果它不在地图中,则不能 运行。您甚至可以通过在空格处拆分字符串并将数组分布在函数参数上来允许参数。像这样:

const instructions = {
    goLeft: player.goLeft.bind(player),
    goRight: player.goRight.bind(player),
    attackInFront: player.attackInFront.bind(player)
};
function processInstruction(instruction_string) {
    const pieces = instruction_string.split(' ');
    const command = pieces[0];
    const args = pieces.slice(1);
    if (instructions[command]) {
        instructions[command](...args);
    } else {
      // Notify the user their command is not recognized.
    }
};

有了它,玩家可以输入 goLeft 5 6 之类的东西,它会调用 player.goLeft(5,6),但如果他们尝试输入 otherFunction 20 40,它只会说无法识别,因为 otherFunction 不在地图中。

这个问题听起来与 SQL Injection 问题相似。我建议你使用类似的解决方案。在用户输入和您的执行之间创建一个抽象层,类似于在存储过程中使用参数。

让用户键入 'ATTACK FRONT' 等关键字,然后将该输入传递给解析字符串的函数,查找关键字,然后返回 'player.attackInFront()' 进行评估。

通过这种方法,您可以为用户简化语法,并将可能的操作限制在您允许的范围内。

我希望这不是太含糊。祝你好运!

从您的编辑来看,您似乎正在为玩家寻找一种面向对象的方法。我不确定您现有的实施需求,但它看起来像这样。

function Player() {
  this.vision = {
    left: '',
    // and so on
  }
}

Player.prototype.updateVisibilities = function() {
  // to modify the values of this.visibility for each player
}

Player.prototype.moveLeft = function() {

}

不要为用户提供任意界面(例如使用 eval 的输入文本字段)来修改其属性。做一个UI层来控制这个逻辑。诸如按钮之类的东西,明确地 运行 functions/methods 在播放器上操作的输入。他们应该拥有什么属性不应该由玩家决定。