You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用PDO防护含GET参数拼接的PHP SQL查询免受SQL注入?

使用PDO修复IN条件的SQL注入风险

你的代码直接把zeme和kraj参数拼进SQL的IN子句,哪怕替换了%2C也完全挡不住SQL注入——攻击者可以轻松构造恶意参数篡改查询逻辑,甚至获取敏感数据。下面是修复方案,全程用PDO参数绑定来规避风险:

步骤1:安全处理用户输入并生成占位符

首先,我们需要把用户传入的逗号分隔值拆分成数组,过滤掉无效值(假设zeme和kraj都是整数ID),然后为每个有效值生成对应的占位符:

$params = []; // 存储所有要绑定的参数
$podminkazeme = "";
$podminkakraj = "";

// 处理zeme参数
if (isset($_GET["zeme"]) && !empty($_GET["zeme"])) {
    // 拆分逗号分隔的值($_GET已经自动解码,无需额外处理%2C)
    $zemeValues = explode(',', $_GET["zeme"]);
    // 过滤为整数,避免非数字注入
    $zemeValues = array_map('intval', $zemeValues);
    // 移除空值
    $zemeValues = array_filter($zemeValues);
    
    if (!empty($zemeValues)) {
        // 生成对应数量的命名占位符
        $placeholders = [];
        foreach ($zemeValues as $index => $value) {
            $key = ":zeme_" . ($index + 1);
            $placeholders[] = $key;
            $params[$key] = $value;
        }
        $podminkazeme = "and nb.zemehledani in (" . implode(', ', $placeholders) . ")";
    }
}

// 处理kraj参数,逻辑和zeme一致
if (isset($_GET["kraj"]) && !empty($_GET["kraj"])) {
    $krajValues = explode(',', $_GET["kraj"]);
    $krajValues = array_map('intval', $krajValues);
    $krajValues = array_filter($krajValues);
    
    if (!empty($krajValues)) {
        $placeholders = [];
        foreach ($krajValues as $index => $value) {
            $key = ":kraj_" . ($index + 1);
            $placeholders[] = $key;
            $params[$key] = $value;
        }
        $podminkakraj = "and nb.krajhledani in (" . implode(', ', $placeholders) . ")";
    }
}

步骤2:执行预处理语句

保持原有的SQL拼接逻辑,但执行时传入参数数组:

$conn = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
// 开启PDO异常模式,方便调试
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$sqljednotkaa = "
  select nb.*, 
    dv.nazev as developer, 
    UNIX_TIMESTAMP(nb.datumAktualizace) as datumAktualizace, 
    UNIX_TIMESTAMP(nb.datumPripomenuti) as datumPripomenuti, 
    uz.nazev as skladUpravil, 
    uzm.nazev as makler, 
    tp.nazev as typProdeje, 
    dal.nazev as nazevdalnice
  from nabidka nb 
  left join uzivatele uz on uz.id=nb.skladUpravil 
  left join uzivatele uzm on uzm.id=nb.makler 
  left join typProdeje tp on tp.id=nb.typProdeje 
  left join developer dv on dv.id=nb.developer
  left join dalnice dal on dal.id=nb.dalnice 
  where nb.emptyid is null 
    $podminkaid 
    $podminkastav 
    $podminkaupraveno 
    $podminkavelikost 
    $podminkacena 
    $podminkamakler 
    $podminkaexport 
    $podminkatypprodeje 
    $podminkatypnemovitosti 
    $podminkazeme 
    $podminkadalnice 
    $podminkakraj 
    $podminkaokres 
    $podminkadeveloper 
    $podminkatechnickeparametry 
    $podminkahledanislovo 
  order by nb.emptyid asc $razenipodminka";

$stjednotkaa = $conn->prepare($sqljednotkaa);
// 传入参数数组执行预处理语句
$stjednotkaa->execute($params);

关键注意点

  • 不要依赖字符串替换防护注入:哪怕替换了逗号,攻击者仍可传入1); DROP TABLE nabidka;--这类恶意值,直接替换完全无效。
  • 验证输入类型:如果zeme和kraj是字符串(比如国家代码),可改用trim()过滤或正则验证格式,再绑定参数。
  • 异常模式调试:开启ERRMODE_EXCEPTION能快速定位SQL执行中的问题,上线后可根据需求调整错误处理逻辑。

内容的提问来源于stack exchange,提问作者strejcekmichal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 10:43:17