2

只要我不使用 $sort 作为传入参数,我就无法弄清楚为什么排序会起作用。下面的示例将用于排序:

$sort = "quantity desc";

$sql = " with items as (
SELECT i.[item_id]
,i.[name]
,i.[value]
,i.[quantity]
,i.[available]
,isnull(r.awarded, 0) as awarded
, ROW_NUMBER() OVER(
  ORDER BY $sort
) rowNumber 
FROM [Intranet].[dbo].[Goodwell_Item] i
LEFT JOIN (
SELECT r.item_id
, COUNT(1) awarded 
from [Intranet].[dbo].[Goodwell_Reward] r
group by r.item_id
) as r
ON i.item_id = r.item_id
)
SELECT * 
FROM items 
WHERE rowNumber BETWEEN (?) and (?)
and ( (?) = '' OR (available = (?)))
";

$params = array( $pagify['startFrom'], $end, $available, $available );

$stmt = sqlsrv_query( $conn, $sql, $params );

但是,如果我将使用 ORDER BY 的行更改为:

ORDER BY (?)

并将其添加到我的 $params 中,如下所示:

$params = array($sort, $pagify['startFrom'], $end, $available, $available );

然后由于某种原因排序被忽略。

请告诉我如何让排序以不允许 SQL 注入的方式工作。

4

1 回答 1

0

我现在正在处理这个确切的问题,在网上找不到任何帮助。

我努力了:

 $query = "SELECT * FROM {$this->view} WHERE SeriesID = ? ORDER BY ? ";
 $result = $conn->getData($query, array($seriesID,$sortBy));

$query = "SELECT * FROM {$this->view} WHERE SeriesID = ? ORDER BY ? ?";
$result = $conn->getData($query, array($seriesID,$sortBy,$sortOrder));

在这两种情况下,我都没有错误,也没有结果。

我认为安全解决这个问题的唯一方法是在查询之前使用 switch 语句来手动验证可接受的值。但是,除非您只处理一个表,否则您无法知道 SortBy 列的可能值是什么。

但是,如果您只是假设此时的值已经被清除,您可以使用非参数化版本,如下所示:

 $query = "SELECT * FROM {$this->view} WHERE SeriesID = ? ORDER BY " . $sortBy . " " . $sortOrder;
 $result = $conn->getData($query, array($seriesID));

我打算做的是确保在将 sortBy 和 sortOrder 传递给包含此代码的方法之前对其进行验证。通过这样做,我调用代码的每个地方都负责在发送数据之前验证数据。调用代码将知道它正在调用的表(或本例中的视图)的有效可能值。(在这种情况下,我是两段代码的作者,所以我知道它是安全的。)

所以,简而言之,只要确保代码中此时的值已经被清理和安全,并将该责任推到调用此代码的代码的上一级。

于 2015-02-04T21:19:54.037 回答