防止使用Laravel为批量准备的原始查询注入SQL


Prevent SQL injection for bulk prepared raw query using Laravel

这是我的查询:

$last = count($list)-1;
$sql = 'INSERT INTO table (col1, col2, col3) VALUES ';
for($i=0; $i<$last; $i++) {
    $sql .= '("'. $list[$i]['col1'] .'", "'. $list[$i]['col2'] .'", '. $list[$i]['col3'] .'), ';
}
$sql .= '("'. $list[$last]['col1'] .'", "'. $list[$last]['col2'] .'", '. $list[$last]['col3'] .') ';
$sql .= 'ON DUPLICATE KEY UPDATE ';
for($i=0; $i<$last; $i++) {
    $sql .= 'col3 = '. $list[$i]['col3'] .', ';
}
$sql .= 'col3 = '. $list[$last]['col3'];
DB::statement($sql);

无PHP查询:

INSERT INTO table (col1, col2, col3) VALUES
    ( $list[$i]['col1'] , $list[$i]['col2'] , $list[$i]['col3'] ),
    ...
    ( $list[$i]['col1'] , $list[$i]['col2'] , $list[$i]['col3'] )
ON DUPLICATE KEY UPDATE
    col3 = $list[$i]['col3'],
    ...
    col3 = $list[$i]['col3'];

我看过这个和这个。我有点不清楚我应该怎么做。我应该这样做吗?

DB::connection()->getPdo()->quote($sql);

我还读到你可以沿着以下路线做一些事情:

DB::escape($sql)

对于使用Laravel的上述查询,防止SQL注入的最佳和最简单的方法是什么?

防止SQL注入的最佳和最简单的方法是使用参数化查询。如何对批量插入进行操作已经回答了很多次,例如:用PDO准备的语句插入多行

编辑:

为了使其清晰明了,要在Laravel中执行参数化查询,请执行

DB::insert($query, $params);

在纯PDO回答中,它是

$stmt = DB::getInstance()->prepare($query);
$stmt->execute($params);

如何为批量插入准备$query$params的问题已经得到了回答,并对其利弊进行了大量讨论,出现了一些针对边缘情况的替代解决方案。请阅读并理解它是如何工作的。

在使用原始查询时看起来像是一个问题。发现了一篇很棒的文章,想把它传给其他可能需要的人。http://fideloper.com/laravel-raw-queries

Laravel确实使用了barry提到的准备好的语句,但似乎需要在绑定数组中专门传递变量,才能在原始查询中实现这一点。

 $someVariable = Input::get("some_variable");
$results = DB::select( DB::raw("SELECT * FROM some_table WHERE some_col = :somevariable"), array(
   'somevariable' => $someVariable,
 ));

我认为这就是它,除非有人能用纯Eloquent做到这一点。希望这能帮助其他人尝试做类似的事情。

由于我使用col1+col2作为密钥,我不得不创建一个复合的唯一密钥,如下所示:

CREATE UNIQUE INDEX col1_col2 ON table (col1, col2)

这是给子孙后代的:

$last = count($list)-1;
$sql = 'INSERT INTO table (col1, col2, col3) VALUES ';
$values = [];
for($i=0; $i<$last; $i++) {
    $sql .= '( ?, ?, ? ), ';
    $values[] = $list[$i]['col1'];
    $values[] = $list[$i]['col2'];
    $values[] = $list[$i]['col3'];
}
$sql .= '( ?, ?, ? ) ';
$values[] = $list[$last]['col1'];
$values[] = $list[$last]['col2'];
$values[] = $list[$last]['col3'];
$sql .= 'ON DUPLICATE KEY UPDATE ';
$sql .= 'col3 = VALUES(col3)';
DB::statement($sql, $values);

干杯!