2016-11-05 103 views
0

爲了避免SQL注入,我做了一些研究並基於this答案我開始使用MySQLi編寫的statemets。這一切都很順利,直到我根據用戶點擊的內容從前端發送的參數order byorder type。爲了更具體一些,我有一些表和一些標題,用戶可以安排數據考慮名稱,價格,日期等,他也可以選擇ASCDESC。我將它存儲到一些隱藏的輸入類型中,所以我猜想他們可能會使用firebug來更改它。正因爲如此,我需要確保他們不能將任何東西注入到我的數據庫中。PHP | MySQLi準備的語句 - 處理順序和順序類型參數

$stmt = $dbConnection->prepare('SELECT * FROM mytable WHERE 1 ORDER BY ? ?'); 
$stmt->bind_param('ss', $_GET['order_by'], $_GET['order_type']); 

看來我得到一個錯誤。我做了一些研究,有人說沒有解決方案,另一個人說唯一的解決方案是硬編碼,另一個人說,我必須退出使用準備好的語句,並嘗試mysql_real_escape_string,但在我回答有人說:

如果您使用的是最新的PHP版本,下面列出的mysql_real_escape_string 選項將不再可用

所以我gueess這是不是也是這樣。所以我的問題仍然存在,接下來我應該做什麼?有這個問題的解決方案嗎?

+0

您只能使用參數的值,您不能用它們來替換表和列的名稱。 – Barmar

+0

'mysql_real_escape_string'不可用的原因是因爲'mysql'擴展名不見了。但是如果你使用'mysqli',它有'mysqli_real_escape_string'。但這對此沒有用處,因爲它用於轉義字符串而不是列名。 – Barmar

回答

1

SQL不允許列別名,表達式或關鍵字的參數。您需要直接將它們插入查詢:

$stmt = $dbConnection->prepare('SELECT * FROM mytable WHERE 1 ORDER BY '.$_GET['order_by'].' '.$_GET['order_type'); 

如果這些正在由用戶提供的,你應該把它們放入查詢字符串之前對其進行驗證。

+0

如果我必須自己驗證他們,爲什麼我應該使用準備好的statemets? ..因爲他們不處理這個,而不是我? – paulalexandru

+1

@paulalexandru如果查詢有其他參數,則使用準備好的語句。 – Barmar

+0

@Barmar - 爲什麼其他參數?爲什麼不是所有的參數?這個參數來自用戶端,他可以編輯它們,如果他想要的話。 – paulalexandru

2

不能使用列名稱的參數,只能使用值。只需檢查列名是否有效。

$allowed_order_by = array('col1', 'col2', 'col3', ...); 
$allowed_order_type = array('asc', 'desc', ''); 
if (in_array(strtolower($_GET['order_by']), $allowed_order_by) && 
    in_array(strtolower($_GET['order_type'], $allowed_order_type)) { 
    $stmt = $dbConnection->prepare(" 
     SELECT * FROM mytable 
     ORDER BY {$_GET['order_by']} {$_GET['order_type']}"); 
    $stmt->execute(); 
} 
+0

'$ _GET ['order_ty [e]'正在拋出語法突出顯示。你可能意思是'$ _GET ['order_type']' –

+0

@ Fred-ii-隨意編輯這樣的明顯的拼寫錯誤 – Barmar

+0

我只有TBH,並不完全確定可能是另一個數組。 –