如何从全局范围中切断功能

时间:2019-08-22 20:42:41

标签: javascript eval xss p5.js

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

我了解不让人们使用eval的全部目的是为了避免意外的跨站点脚本编写,但是我不确定其他方法。如果您有任何建议,请对此发表评论。

我问了一些有关该怎么做的人,大多数人建议以某种方式更改范围(这是我无法弄清楚的)或向我的代码中的每个函数添加一些奇怪的参数,这些参数必须是特定的字符串来执行任何功能,但这似乎很麻烦,由于我是使用p5js在浏览器中制作游戏的,因此只需检查一下元素并查看密码是容易的。

基本上每个字符都有一个称为“指令”的变量,它只是一串javascript。然后,游戏的每一帧我都通过执行eval(playerList [i] .instruction);

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

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

编辑2:很抱歉本文中缺少代码,但是由于我的编写方式,一半的逻辑是在服务器端编写的,而另一半则是在客户端工作的。将会有点大,说实话,我不确定我的代码可读性如何,到目前为止,我还是得到了很大的帮助,对此我非常感谢。谢谢所有回答的人

3 个答案:

答案 0 :(得分:2)

请勿使用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,则只会说它未被识别,因为{{1} }不在地图上。

答案 1 :(得分:1)

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

让用户键入诸如“ ATTACK FRONT”之类的关键字,然后将该输入传递给解析字符串,查找关键字的函数,然后传递回“ player.attackInFront()”以进行评估。

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

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

答案 2 :(得分:0)

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

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层来控制此逻辑。诸如按钮之类的东西,是明确运行在播放器上运行的功能/方法的输入。应该由玩家决定应该拥有哪些属性。