首页 > 解决方案 > 如何在 Yii2 中安全地使用客户端定义的查询字符串参数生成 ActiveQuery?

问题描述

有没有一种安全的方法来为Yii2 ORM生成带有查询字符串参数的条件子句?例如,我们需要一些食品的列表,按它们的属性过滤:

GET /food/?weight[>]=1000&calories=[<]=200

并且产品有很多不同的属性:重量、卡路里、数量、价格。

我希望可以编写类似(简化代码)的内容:

 $query = new \yii\db\Query();
 foreach ($_GET as $parameter => $condition){
    foreach ($condition as $operator => $value){
        $query->where(new SimpleCondition($parameter, $operator, $value));
    }
 }

但我怀疑这种方法是否安全

所以,有三个问题:

  1. 如何安全地从 url 定义属性?我们可以在使用 in子句之前清理查询字符串参数名称(不是values )吗?ActiveQuery::where
  2. 正确定义运算符的方法是IN, AND, OR, >, <, >=, <=, etc.什么?
  3. 是否有任何用于过滤的原生 Yii2 组件或者我应该使用第三方模块?

标签: phpyii2query-stringsql-injection

解决方案


最后,我找到了解决方案。Yii2 似乎通过DataFilter类提供了这样的功能。该类的官方文档和使用指南

根据文档

  1. 定义验证模型。

    class SearchModel extends \yii\base\Model
    {
        public $id;
        public $name;
    
        public function rules()
        {
            return [
                [['id', 'name'], 'trim'],
                ['id', 'integer'],
                ['name', 'string'],
            ];
        }
    }
    
  2. 创建过滤器:

    $filter = new DataFilter(['searchModel' => $searchModel]);
    
  3. 用数据填充过滤器,验证

    if ($filter->load(\Yii::$app->request->get())) { 
       $filterCondition = $filter->build();
       if ($filterCondition === false) { // if error occure
           // the errors are stored in the filter instance
           return $filter;
       }
    }
    
  4. Query在过滤器中使用内置条件

    $query->andWhere($filterCondition);
    

推荐阅读