具有可变列的准备好的语句

Prepared statements with variable columns

我正在为我一直在做的游戏创建一个数据库,我需要用户能够互相残杀,所以我设置了 table 这样的:

...
`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 注入。有什么好的方法可以将 "bind" 列名添加到查询中,以便我可以安全地修改 table 吗?

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

有什么想法吗?

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

一般来说,对于白名单,您会创建一组有效标识符并检查传递的标识符是否在列表中。例如:

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

在你的情况下你可以

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

然后检查 $id[1, 4] 范围内。

我会使用正则表达式/^[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

的数字