PDO准备好的语句-语法和清理 [英] PDO prepared statement - syntax and sanitization

查看:47
本文介绍了PDO准备好的语句-语法和清理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用以下内容更新数据库:

I'm trying to update my database with the following:

$fields = array(
    'titulo',
    'tipo_produto',
    'quantidade_peso',
    'unidade_de_venda',
    'unidades_por_caixa',
    'caixas_piso',
    'pisos_palete',
    'tipo_palete',
    'unidades_palete',
    'caixas_palete',
    'uni_diametro',
    'uni_largura',
    'uni_profundidade',
    'uni_altura',
    'caixa_largura',
    'caixa_profundidade',
    'caixa_altura',
    'altura_palete',
    'volume_unidade',
    'volume_caixa',
    'volume_palete',
    'peso_caixa',
    'peso_palete'
);
$sql = 'UPDATE ficha_item SET '.implode(', ', array_map(create_function('$value', 'return "$value=\"" . $_POST["$value"] ."\"";'), $fields)).' WHERE id=?';

$stmt = $db->prepare($sql);

$stmt->execute(array($_POST['item_id']));
$stmt->closeCursor();

这似乎工作得很好,但是我想知道它的安全性吗?

This seems to work pretty well, but I'm wondering about the security, is this sanitized at all?

我尝试(没有成功)另一种解决方案后想到了这个解决方案:

I came up with this solution after attempting (with no success) another solution:

$fields = array(
    'titulo',
    'tipo_produto',
    'quantidade_peso',
    'unidade_de_venda',
    'unidades_por_caixa',
    'caixas_piso',
    'pisos_palete',
    'tipo_palete',
    'unidades_palete',
    'caixas_palete',
    'uni_diametro',
    'uni_largura',
    'uni_profundidade',
    'uni_altura',
    'caixa_largura',
    'caixa_profundidade',
    'caixa_altura',
    'altura_palete',
    'volume_unidade',
    'volume_caixa',
    'volume_palete',
    'peso_caixa',
    'peso_palete'
);
$sql = 'UPDATE ficha_item SET ? WHERE id=?';

$valuesClause = implode(', ', array_map(create_function('$value', 'return "$value=\"" . $_POST["$value"] ."\"";'), $fields));

$stmt = $db->prepare($sql);

$stmt->execute(array($valuesClause, $_POST['item_id']));
$stmt->closeCursor();

完全没有错误,但是我的数据库无法更新.我的第一个解决方案是否已全部消毒?我的最初想法出了什么问题?我认为这与PDO如何在执行过程中清理查询有关……但是我对在何处使用它一无所知.

No errors at all, but my database would not be updated. Is my first solution sanitized at all? What went wrong with my original idea? I'm thinking it has something to do with how PDO sanitizes the query on the execute... but I'm out of ideas on where to go with it.

注意::数据库列名称和输入名称相同,这就是$value起作用的原因.如果您还想知道,由于实时的PHP版本,匿名函数毫无疑问.

NOTE: The database column names and the input names are the same, that is why $value works. In case you're also wondering, anonymous functions are out of question due to live PHP version.

推荐答案

$fields = array(
    'titulo',
    'tipo_produto',
    'quantidade_peso',
    'unidade_de_venda',
    'unidades_por_caixa',
    'caixas_piso',
    'pisos_palete',
    'tipo_palete',
    'unidades_palete',
    'caixas_palete',
    'uni_diametro',
    'uni_largura',
    'uni_profundidade',
    'uni_altura',
    'caixa_largura',
    'caixa_profundidade',
    'caixa_altura',
    'altura_palete',
    'volume_unidade',
    'volume_caixa',
    'volume_palete',
    'peso_caixa',
    'peso_palete'
);
$sql="UPDATE ficha_item SET ".implode(", ",array_map(function($s){
    return "$s = ?";
},$fields))." WHERE id=?";
print_r($sql);

输出:

UPDATE ficha_item SET titulo = ?, tipo_produto = ?, quantidade_peso = ?, unidade_de_venda = ?, unidades_por_caixa = ?, caixas_piso = ?, pisos_palete = ?, tipo_palete = ?, unidades_palete = ?, caixas_palete = ?, uni_diametro = ?, uni_largura = ?, uni_profundidade = ?, uni_altura = ?, caixa_largura = ?, caixa_profundidade = ?, caixa_altura = ?, altura_palete = ?, volume_unidade = ?, volume_caixa = ?, volume_palete = ?, peso_caixa = ?, peso_palete = ? WHERE id=?

这是您prepare所需的 SQL语句.现在获取您的准备好的声明:

This is the SQL statement that you need to prepare. Now to get your prepared statement:

$stmt=$db->prepare($sql);
$stmt->execute(array_merge(array_map(function($s){
    return $_POST[$s];
},$fields),array($_POST["item_id"])));

没有可供我测试的数据库,但这应该是正确的轨道.

No database for me to test, but this should be the right track.

请注意,我只是遵循您的风格";即使此代码将所有$_POST都视为参数,从而避免了SQL注入,但仍假定每个$_POST[$fields[$idx]]都存在,并且任何用户都可以轻易地将其破坏,因此应该在此进行清理.

Note that I'm just following your "style"; Even though this code is treating all $_POST as parameters and thus avoiding SQL injection, it's assuming that every $_POST[$fields[$idx]] exists, which can be easily broken by any user, so this is where you should sanitize.

修改:

由于已更新为不能使用匿名函数,因此可以手动构造所需的数组:

Since you've updated that you can't use anonymous function, you can construct the required arrays manually:

$cache=array();
foreach($fields as $field)
    $cache[]="$field = ?";
$sql="UPDATE ficha_item SET ".implode(", ",$cache)." WHERE id=?";

$cache=array();
foreach($fields as $field)
    $cache[]=isset($_POST[$field])?$_POST[$field]:null;
$cache[]=$_POST["item_id"]
/*...*/
$stmt->execute($cache);

这篇关于PDO准备好的语句-语法和清理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆