0

你能否告诉这两个代码片段在 yii 中是否安全。香精1:

 $numberOfRows = $this->updateAll(array('full_path' => $target, 'title' => $name,                'machine_name' => $name), 'full_path = :path', array(':path' => $path));

我应该在这个查询中转义 $target 和 $name 吗?

片段 2:

$sql = "UPDATE folders";
$sql .= " SET full_path = CONCAT('" . $target . "',SUBSTR(full_path, " . (strlen($path)  + 1) . ", LENGTH(full_path)-1))";
$sql .= " WHERE full_path LIKE '" . $path . "%'";
$command = $this->dbConnection->createCommand($sql);
$command->execute();

我应该在这两个片段中使用 CDbConnection::quoteValue() 或类似的东西来逃避 $target 和 full_path 吗?我还介绍了如何在 Fragment 2 中转义路径以避免与 LIKE (%, _) 一起使用的特殊符号的问题。

我使用绑定和转义 %_ 对片段 2 进行了更改:

$sql = "UPDATE folders";
$sql .= " SET full_path = CONCAT(:target, SUBSTR(full_path, " . (strlen($path) + 1) . ", LENGTH(full_path)-1))";
$sql .= " WHERE full_path LIKE  :pathFilter";
$command = $this->dbConnection->createCommand($sql);

//escape %_ that can be used in SQL LIKE expression
$pathFilter = addcslashes($path, '%_') . '%';

$command->bindParam(":pathFilter", $pathFilter, PDO::PARAM_STR);
$command->bindParam(":target", $target, PDO::PARAM_STR);

$command->execute();

这是对的吗?有没有更优雅的方法呢?

4

2 回答 2

0

你有两个选择:

a)使用模型对象,例如,在您的情况下,您可以为文件夹表和任何其他要插入/更新数据的关联表提供模型类。这将帮助您使用一组模型(如果适合您的话)。模型类具有在插入数据库之前验证数据的内置函数。例如CActiveRecord 保存方法。进一步阅读此内容以了解相关的安全细节

使用假设您有Folder模型:

 $path='path to be updated';
 $criteria=new CDbCriteria;
  $criteria->compare('full_path',$path,true);
  $folder=Folder::model()->find($criteria);
  if($folder){
   $folder->attributes=$data;
    if($folder->save()){
      echo 'updated successfully';
    }else{
      echo 'invalid data';
    }
  }

b) 如果不需要创建模型类,请使用Binding Parameters Details 文章,参见 #5 Binding Parameters

假设您构造了 $full_path 和 $path 变量

  //$full_path=[construct using php]
  //$path=[construct using php]
  $sql = "UPDATE folders SET full_path = :newPath  WHERE full_path LIKE :oldPath"
  $command = $this->dbConnection->createCommand($sql);
  $command->bindParam(":newPath", $full_path, PDO::PARAM_STR);
  $old_path=addcslashes($path,'%_').'%'; 
  $command->bindParam(":oldPath", $old_path, PDO::PARAM_STR);
  $command->execute();

希望这会有所帮助

于 2013-10-07T17:14:24.667 回答
0

说到更优雅的方式,你总是可以避免命名参数,这将大大缩短你的代码:

$sql  = "UPDATE folders SET";
$sql .= " full_path = CONCAT(?, SUBSTR(full_path, ?, LENGTH(full_path)-1))";
$sql .= " WHERE full_path LIKE ?";

//escape %,_ and \ that can be used in SQL LIKE expression
$pathFilter = addcslashes($path, '\%_') . '%'; // I've added a slash here

$command = $this->dbConnection->createCommand($sql);
$command->execute([$target, strlen($path) + 1, $pathFilter]);
于 2013-10-07T14:05:49.197 回答