具有可变列的已准备语句


Prepared statements with variable columns

我正在为我一直在开发的游戏创建一个数据库,我需要用户能够杀死对方,所以我设置了这样的表:

...
`alive1` => Player 1's status
`alive2` => Player 2's status
`alive3` => Player 3's status
`alive4` => Player 4's status
...

我需要能够根据具体情况修改数据库中的这些列,并直接使用用户的输入。然而,这样做:

$stmt = $link->prepare("UPDATE `games` SET `alive{$_GET["player"]}`=0 WHERE `id`=?")

易受SQL注入的攻击。有没有一种好的方法可以将列名"绑定"到查询,这样我就可以安全地修改表了?

$_GET["播放器"]的正确输入应该是整数1..4,所以如果需要的话,我想我可以直接检查输入,并确保它是这四种可能性之一,但我希望有一个更优雅的解决方案。这可能会在稍后的另一个项目中再次出现,在该项目中,可能的输入集会大得多,并且对每个情况进行硬编码将非常耗时。

有什么想法吗?

标识符不能绑定到准备好的语句中,因此您应该将它们列入白名单。

通常,对于白名单,您可以创建一个有效标识符数组,并检查传递的标识符是否在列表中。例如:

$validColumns = array('alive1', 'alive2', 'alive3', 'alive4');
$col = 'alive' . $_GET["player"];
$isSafeToUse = in_array($col, $validColumns);

在你的情况下,你可以只是

$id = (int)$_GET["player"];

然后检查CCD_ 1是否在CCD_。

我会使用一个正则表达式/^[1-4]$/

if(preg_match('/^[1-4]$/', $_GET['player'])){
    $stmt = $link->prepare('UPDATE `games` SET `alive' . $_GET['player'] . '` =0 WHERE `id`=?');
} else {
    die;
}

为了在未来的项目中使用它,您可以将其扩展到/^[0-9]{1,3}$/,这将允许您接受一个高达999的数字