2014-10-31 91 views
4

結合起來在Laravel 4中,我想保護SQL注入中的一些複雜數據庫查詢。這些查詢使用查詢生成器和DB :: raw()的組合。下面是一個簡化的例子:阻止SQL查詢將查詢生成器與DB :: raw()

$field = 'email'; 
$user = DB::table('users')->select(DB::raw("$field as foo"))->whereId(1)->get(); 

我讀過Chris Fidao's tutorial,有可能通過綁定到select()方法的陣列,且因此正確地防止SQL注入,通過使用準備的語句。例如:

$results = DB::select(DB::raw("SELECT :field FROM users WHERE id=1"), 
       ['field' => $field] 
      )); 

這有效,但該示例將整個查詢放入原始語句中。它不會將查詢生成器與DB :: raw()結合在一起。當我嘗試類似的東西使用的第一個例子:

$field = 'email'; 
$user = DB::table('users')->select(DB::raw("$field as foo"), ['field' => $field]) 
      ->whereId(1)->get(); 

...然後我得到一個錯誤:用strtolower()預計參數1是字符串數組給定

什麼是正確的方法阻止將查詢生成器與DB :: raw()相結合的查詢進行SQL注入?

回答

2

我發現查詢生成器中有一個名爲setBindings()方法,其可在這種情況下非常有用:

$field = 'email'; 
$id = 1; 
$user = DB::table('users')->select(DB::raw(":field as foo")) 
     ->addSelect('email') 
     ->whereId(DB::raw(":id")) 
     ->setBindings(['field' => $field, 'id' => $id]) 
     ->get(); 
2

雄辯使用引擎蓋下的PDO來消毒物品。它不會清理添加到SELECT語句的項目。

但是,mysqli_real_escape_string方法對於清理SQL字符串仍然很有用。

也考慮(或相反)保留來自用戶表的有效字段名稱的數組,並檢查它以確保沒有使用無效值。

$allowedFields = ['username', 'created_at']; 

if(! in_array($field, $allowedFields)) 
{ 
    throw new \Exception('Given field not allowed or invalid'); 
} 

$user = DB::table('users') 
      ->select(DB::raw("$field as foo")) 
      ->whereId(1)->get(); 
+0

感謝。我曾希望能夠仍然使用預準備語句,但mysqli_real_escape_string將工作。我認爲如果Laravel文檔能夠顯示推薦的方法來防止原始查詢的SQL注入,而不是僅僅警告風險,那將會很好。 – mtmacdonald 2014-10-31 12:29:40