php – 将mySQL插入和更新语句切换到PDO预处理语句以防止SQL注入

发布时间:2022-04-30 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了php – 将mySQL插入和更新语句切换到PDO预处理语句以防止SQL注入脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
@H_304_2@
我正在尝试将这些MysqL INSERT INTO和Update语句切换到PDO预处理语句(主要是为了sql注入),但是我在使语法正确方面遇到了一些困难.

我目前正在使用两种类型的INSERT / Update语句:

声明1 – 名称是硬编码的

$qry = "INSERT INTO customer_info(fname,lname,email,user_name,password)
VALUES('$_POST[fname]','$_POST[lname]','$_POST[email]','$user_name','".sha1($salt + $_POST['password'])."')"; 
$result = @MysqL_query($qry)

声明2 – 动态添加名称

不是列出每个元素的名称,而是动态添加大多数名称(名称被引用为$fieldlist或$setlist,值为$vallist).唯一的硬编码名称/值是user_id或者是数组.我在下面列出了完整的代码.

$result = MysqL_query('UPDATE fIT_table  SET '.$setlist.' WHERE user_id='.$user_id);
if (MysqL_affected_rows()==0) {
$result = MysqL_query('INSERT INTO fit_table ('.$fieldlist.') VALUES ('.$vallist.')'); };

这就是我尝试过的:

声明1 – 基于此帖子https://stackoverflow.com/a/60530/1056713

$stmt = $conn->PRepare("INSERT INTO customer_info VALUES(:fname,:lname,:email,:user_name,:password)");
$stmt->bindValue(':fname',$fname);
$stmt->bindValue(':lname',$lname);
$stmt->bindValue(':email',$email);
$stmt->bindValue(':user_name',$user_name);
$stmt->bindValue(':password ',$password);
$stmt->execute();

声明2 – 基于此PDO包装器https://github.com/Xeoncross/DByte/blob/master/DB.php(在本文中引用https://stackoverflow.com/a/12500462/1056713)

static function insert($fit_table,array $fieldlist){
$query = "INSERT INTO`$fit_table`(`" . implode('`,`',array_keys('.$fieldlist.')). '`) 
VALUES(' . rtrim(str_rePEat('?,',count($fieldlist = array_values('.$vallist.'))),') . ')';
return DB::$p
? DB::column($query . 'RETURNING` user_id `',$fieldlist)
: (DB::query($query,$fieldlist) ? static::$c->lastInsertId() : NULL);
}

语句2的完整代码(这是目前动态添加名称的方式)

// INSERT    
$fieldlist=$vallist='';
foreach ($_POST as $key => $value) {
    if ($key=='pants_waistband'){$value= implode(',$value);}        
    $fieldlist.=$key.',';
    $vallist.='\''.($value).'\',';
}
$fieldlist=substr($fieldlist,-1);
$vallist=substr($vallist,-1);
$fieldlist.=',user_id';
$vallist.=','.$user_id;
// UPDATE
$setlist='';
foreach ($_POST as $key => $value) {
    if ($key=='pants_waistband'){$value= implode(',$value);}  
    $setlist.=$key .'=\''.$value.'\',';
}
$setlist=substr($setlist,-1); 

$result = MysqL_query('UPDATE fit_table SET '.$setlist.' WHERE user_id='.$user_id);
if (MysqL_affected_rows()==0) {
$result = MysqL_query('INSERT INTO fit_table ('.$fieldlist.') VALUES ('.$vallist.')');}

解决方法

看,白名单并不像看起来那么无聊!
动态查询很棒,没有理由放弃这个想法.
至少你可以使它成为动态的,以避免所有这些重复.

PDO有一个很棒的功能 – 它可以接受带有值的数组,不需要重复绑定.
它可以很简单

$stmt = $conn->prepare('INSERT INTO customer_info VALUES(?,?,?)');
$stmt->execute($_POST);

如果$_POST包含正确顺序的确切字段数,它将被执行.
但是一旦我们在查询中需要字段名称,它将丢失所有自动化(如在您自己的答案中)或变得不安全(如在您之前的动态代码中).

好吧,让它既安全又动态.
你唯一需要的是一个带有允许字段名称的数组,它将是我们的白名单.
然后,您可以使用此数组循环$_POST,动态创建查询.
这是一个自动化过程的功能
它需要三个参数,但实际上只使用一个

function pDOSet($fields,&$values,$source = array()) {
  $set = '';
  $values = array();
  if (!$source) $source = &$_POST;
  foreach ($fields as $field) {
    if (isset($source[$field])) {
      $set.="`$field`=:$field,";
      $values[$field] = $source[$field];
    }
  }
  return substr($set,-2); 
}

它将返回看起来像的字符串

`field1`=?,`field2`=?,`field3`=?

并将填充$values数组以供PDO查询使用.

请注意,MysqL允许INSERT和UPDATE查询的SET语法 – 不需要VALUES语法.所以,这两种功能都有.

对于插入物来说,它就像

$fields = array("fname","lname","email","user_name");
$stmt = $dbh->prepare("UPDATE users SET ".pdoSet($fields,$values));
$stmt->execute($values);

对于任何数量的领域,它都将保持相同的3线程!

对于更新,它需要更长的代码.我们需要为查询添加一些条件,以及向$values数组添加一个成员.

$fields = array("fname",$values)." WHERE id = :id");
$values["id"] = $_POST['id'];
$stmt->execute($values);

唯一的问题是如何添加不在$_POST数组中的自定义字段.
在准备之前,我只是直接在那里添加它们:

$_POST['password'] = sha1($_POST['email'].$_POST['password']);

希望这是你要求的.

只需澄清一件事.准备好的陈述不足以阻止注射,你的案例就是一个很好的例子.他们只处理数据,但保护字段名称是你的负担.然而,你使用的旧MysqL方式没有任何问题.您的代码只缺少相同的白名单(当然还有正确的数据格式).但如果添加,它将使您的mySQL查询像PDO一样安全.

脚本宝典总结

以上是脚本宝典为你收集整理的php – 将mySQL插入和更新语句切换到PDO预处理语句以防止SQL注入全部内容,希望文章能够帮你解决php – 将mySQL插入和更新语句切换到PDO预处理语句以防止SQL注入所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。