【问题标题】:pdo prepare escaping single quotespdo 准备转义单引号
【发布时间】:2015-09-16 07:01:44
【问题描述】:

我在我正在构建的 Web 应用程序中使用 PDO。我一直认为(实际上我错了)使用prepare 应该有助于插入变量中的单引号,但似乎我错过了一些东西。我在插入 L'Aquila 之类的值时遇到错误,其中输入数据中有一个单引号。

我的实际代码是:

        $sql = "INSERT INTO anagrafiche SET
        id_ndg = '$protocol',
        nick = '$nick',
        nome = '$nome',
        cognome = '$cognome',
        ragsoc = '$ragsoc',
        leg_rappr = '$leg_rappr',
        cod_fisc = '$cod_fisc',
        p_iva = '$p_iva',
        cf_estero = '$cf_estero',
        SAE = '$sae',
        RAE = '$rae',
        ATECO = '$ateco',
        CRCODE = '$crcode',
        indirizzo = '$indirizzo',
        civico = '$civico',
        cap = '$cap',
        citta = '$citta',
        prov = '$prov',
        tel = '$tel',
        cell = '$cellulare',
        mail = '$mail',
        note = '$note',
        file_ci = '$file_ci',
        file_cf = '$file_cf',
        file_visura = '$file_visura',
        cittadinanza = '$cittadinanza',
        res_fiscale = '$res_fiscale',
        is_curatore = '$is_curatore',
        is_legale = '$is_legale',
        is_tribunale = '$is_tribunale',
        is_fornitore = '$is_fornitore' ";
    try{
        $s = $pdo->prepare($sql);               
        $s->execute();
    }
    catch (PDOException $e){
        $error = 'Errori nel caricamento: '.$e->getMessage();
    }

当我尝试加载包含单引号的字符串时,我在尝试加载字符串时遇到这样的错误 Piazza d'Armi

错误提示:SQLSTATE[42000]:语法错误或访问 违规:1064 您的 SQL 语法有错误;检查手册 对应于您的 MySQL 服务器版本以获得正确的语法 在'Armi'附近使用,civico ='0',cap ='83100',citta ='Avellino', 证明在第 15 行

我错过了什么?我不认为 PDO 报价可以为我完成这项工作,但也许是我不明白这一点

【问题讨论】:

  • 您已经使用了prepare(),但不是实际的变量绑定。查找bindParam()execute() 的参数。
  • 准备只是第一步。绑定是第 2 步。您应该准备一个带有占位符的查询并将值绑定到这些占位符。自己准备并不比自己运行查询更安全,并且对相同级别的 sql 注入开放。
  • 啊,好的。也应该做bindParam。会试一试。我想现在明白了准备工作的原理。谢谢!
  • 你完全错了......如果你正在准备,你应该使用占位符。照原样,你仍然完全容易受到sql injection attacks
  • 我知道我是。此代码适用于我使用的 Intranet 应用程序,用于从旧应用程序中大量加载经过清理的数据。

标签: php mysql pdo


【解决方案1】:

仅当您执行参数化的预处理语句时,单引号才有帮助,否则您所做的只是字符串连接,并且必须正确形成您的 SQL。

尝试类似:

$sql = "INSERT INTO anagrafiche SET
        id_ndg = :protocol,
        nick = :nick,
        nome = :nome,
        ...
        ";
$params = array(
    ':protocol' => $protocol,
    ':nick' => $nick,
    ':nome' => $nome,
    ...
); 
try{
    $s = $pdo->prepare($sql);               
    $s->execute($params);
} catch (PDOException $e) {
    ...
}

这还为您提供了减轻 SQL 注入攻击的额外优势。

如果您想更进一步并强制执行数据类型,您可以使用bindValue()bindParam()

喜欢:

$sql = "INSERT INTO anagrafiche SET
        id_ndg = :protocol,
        nick = :nick,
        nome = :nome,
        ...
        "; 
try{
    $s = $pdo->prepare($sql);
    $s->bindParam(':protocol', $protocol, PDO::PARAM_ST);
    $s->bindParam(':nick', $nick, PDO::PARAM_ST);
    $s->bindParam(':nome', $nome, PDO::PARAM_ST);
    ...
    $s->bindParam(':some_integer', $some_integer, PDO::PARAM_INT);
    ...           
    $s->execute();
} catch (PDOException $e) {
    ...
}

bindValue()bindParam() 语法相似,但只绑定了绑定参数时的变量值,而不是语句执行时的变量值。

【讨论】:

  • 应该也适用于 bindParams,对吧?列出所有像 $s->bindParam(':protocol', $protocol) 这样的字符串?我只是在问我的知识,但这个语法太棒了!!
  • @LelioFaieta 是的。我也在这里添加了一个bindParam() 示例。我实际上更喜欢bindParam()bindValue()(取决于使用情况)而不是在execute() 中传递数组,因为我喜欢具体说明数据类型,但是有很多人更喜欢在execute() 中传递数组
猜你喜欢
  • 1970-01-01
  • 2022-01-19
  • 2015-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-23
  • 2013-07-10
  • 2012-03-29
相关资源
最近更新 更多