Mysql动态查询[sql注入]
Mysql dynamic query [sql injection]
我通常使用准备好的语句,但在特定页面上我使用的是动态查询,我找不到可靠的方法来防止 SQL 注入。
if(isset($_GET['sub_cat'])){
if($_GET['sub_cat'] != '')
$conditions[] = 'ad_sub_cat='.$_GET['sub_cat'].'';
}
if(isset($_GET['ad_brand'])){
if($_GET['ad_brand'] != '')
$conditions[] = "`ad_brand` LIKE CONCAT('%','".$_GET['ad_brand']."','%') ";
}
if(isset($_GET['min_range'])){
if($_GET['min_range'] != '')
$conditions[] = 'ad_price >='.$_GET['min_range'].'';
}
if(isset($_GET['max_range'])){
if($_GET['max_range'] != '')
$conditions[] = 'ad_price <='.$_GET['max_range'].'';
}
if(isset($_GET['for_r_s'])){
if($_GET['for_r_s'] != '')
$conditions[] = 'for_r_s ='.$_GET['for_r_s'].'';
}
$query = "SELECT posts.ID, posts.ad_title, posts.ad_price, posts.ad_location, posts.ad_sub_cat FROM `posts` WHERE ". implode(' AND ', $conditions) ."";
您可以像对待任何其他查询一样防止 SQL 注入:通过将 查询 与应始终基于硬编码值的查询分开数据。唯一的区别是您需要有条件地建立查询和数据参数列表。
所以代替:
if(isset($_GET['sub_cat'])){
if($_GET['sub_cat'] != '')
$conditions[] = 'ad_sub_cat='.$_GET['sub_cat'].'';
}
你应该写:
if(isset($_GET['sub_cat'])){
if($_GET['sub_cat'] != '') {
$sql_conditions[] = 'ad_sub_cat=:sub_cat';
$parameters['sub_cat'] = $_GET['sub_cat'];
}
}
或者如果使用位置参数而不是命名参数:
if(isset($_GET['sub_cat'])){
if($_GET['sub_cat'] != '') {
$sql_conditions[] = 'ad_sub_cat=?';
$parameters[] = $_GET['sub_cat'];
}
}
你所有的条件依此类推。
然后在最后,您从 $sql_conditions
构建您的 SQL - 其中根本没有用户输入,因此不会被注入 - 并将 $parameters
传递给PDO/mysqli 执行查询。
在将参数添加到查询字符串之前使用 mysqli_real_escape_string
。
例如:
if(isset($_GET['sub_cat']) && $_GET['sub_cat'] != ''){
$sub_cat = mysqli_real_escape_string($connection, $_GET['sub_cat']);
$conditions[] = 'ad_sub_cat='.$sub_cat.'';
}
我通常使用准备好的语句,但在特定页面上我使用的是动态查询,我找不到可靠的方法来防止 SQL 注入。
if(isset($_GET['sub_cat'])){
if($_GET['sub_cat'] != '')
$conditions[] = 'ad_sub_cat='.$_GET['sub_cat'].'';
}
if(isset($_GET['ad_brand'])){
if($_GET['ad_brand'] != '')
$conditions[] = "`ad_brand` LIKE CONCAT('%','".$_GET['ad_brand']."','%') ";
}
if(isset($_GET['min_range'])){
if($_GET['min_range'] != '')
$conditions[] = 'ad_price >='.$_GET['min_range'].'';
}
if(isset($_GET['max_range'])){
if($_GET['max_range'] != '')
$conditions[] = 'ad_price <='.$_GET['max_range'].'';
}
if(isset($_GET['for_r_s'])){
if($_GET['for_r_s'] != '')
$conditions[] = 'for_r_s ='.$_GET['for_r_s'].'';
}
$query = "SELECT posts.ID, posts.ad_title, posts.ad_price, posts.ad_location, posts.ad_sub_cat FROM `posts` WHERE ". implode(' AND ', $conditions) ."";
您可以像对待任何其他查询一样防止 SQL 注入:通过将 查询 与应始终基于硬编码值的查询分开数据。唯一的区别是您需要有条件地建立查询和数据参数列表。
所以代替:
if(isset($_GET['sub_cat'])){
if($_GET['sub_cat'] != '')
$conditions[] = 'ad_sub_cat='.$_GET['sub_cat'].'';
}
你应该写:
if(isset($_GET['sub_cat'])){
if($_GET['sub_cat'] != '') {
$sql_conditions[] = 'ad_sub_cat=:sub_cat';
$parameters['sub_cat'] = $_GET['sub_cat'];
}
}
或者如果使用位置参数而不是命名参数:
if(isset($_GET['sub_cat'])){
if($_GET['sub_cat'] != '') {
$sql_conditions[] = 'ad_sub_cat=?';
$parameters[] = $_GET['sub_cat'];
}
}
你所有的条件依此类推。
然后在最后,您从 $sql_conditions
构建您的 SQL - 其中根本没有用户输入,因此不会被注入 - 并将 $parameters
传递给PDO/mysqli 执行查询。
在将参数添加到查询字符串之前使用 mysqli_real_escape_string
。
例如:
if(isset($_GET['sub_cat']) && $_GET['sub_cat'] != ''){
$sub_cat = mysqli_real_escape_string($connection, $_GET['sub_cat']);
$conditions[] = 'ad_sub_cat='.$sub_cat.'';
}