在 Yii 2 中,当输入数据是通过网址时,为了避免执行冗余的更新SQL,给输入值应用一个过滤器(intval),进而导致衍生出的验证规则失效的分析解决

1、在浏览器中打开网址:http://www.channel-pub-api-localhost.chinamcloud.com/weibo-oauth2/authorize-update?group_id=spider&channel_app_source_uuid=269f68bc098011e9b1c354ee75d2ebc1&user_name=华栖云1658397962&permission=4&status=1&redirect_uri=aHR0cDovL3d3dy56bXQuY29tLw%3D%3D ,此时验证规则生效,如图1

图1

2、验证规则为:permission:可选,权限,1:同步;2:发布;3:同步与发布

            /* 更新微博的微连接的网页应用的用户 */            [['permission'], 'in', 'range' => [self::PERMISSION_SYNC, self::PERMISSION_PUB, self::PERMISSION_SYNC_PUB], 'on' => self::SCENARIO_UPDATE],

3、此时数据库中 permission 的值为 2,updated_at 的值为 1545961613 ,如图2

图2

4、在浏览器中打开网址:http://www.channel-pub-api-localhost.chinamcloud.com/weibo-oauth2/authorize-update?group_id=spider&channel_app_source_uuid=269f68bc098011e9b1c354ee75d2ebc1&user_name=华栖云1658397962&permission=2&status=1&redirect_uri=aHR0cDovL3d3dy56bXQuY29tLw%3D%3D ,permission 的值为 2,由于 permission 字段为 SMALLINT(6) 类型,status 字段为 SMALLINT(6) 类型,而通过网址传递的参数为字符串类型,因此,即使 permission 与 status 的值未发生变化,仍然执行了更新 SQL,执行 SQL 语句如下:

UPDATE `cpa_weibo_weibo_connect_web_app_user` SET `permission`=2, `status`=1, `updated_at`=1546066986 WHERE `id`=17

5、调整验证规则,给输入值应用一个过滤器(intval)

            /* 更新微博的微连接的网页应用的用户 */            [['permission'], 'in', 'range' => [self::PERMISSION_SYNC, self::PERMISSION_PUB, self::PERMISSION_SYNC_PUB], 'on' => self::SCENARIO_UPDATE],
   [['permission', 'status'], 'filter', 'filter' => 'intval', 'on' => self::SCENARIO_UPDATE],

6、在浏览器中打开网址:http://www.channel-pub-api-localhost.chinamcloud.com/weibo-oauth2/authorize-update?group_id=spider&channel_app_source_uuid=269f68bc098011e9b1c354ee75d2ebc1&user_name=华栖云1658397962&permission=&status=1&redirect_uri=aHR0cDovL3d3dy56bXQuY29tLw%3D%3D ,permission 的值为 空字符串,此时验证规则失效,permission 的值更新为 0,执行 SQL 语句如下:

UPDATE `cpa_weibo_weibo_connect_web_app_user` SET `permission`=0, `updated_at`=1546067544 WHERE `id`=17

7、调整验证规则,将过滤器(intval)置于最前

            /* 更新微博的微连接的网页应用的用户 */   [['permission', 'status'], 'filter', 'filter' => 'intval', 'on' => self::SCENARIO_UPDATE],
            [['permission'], 'in', 'range' => [self::PERMISSION_SYNC, self::PERMISSION_PUB, self::PERMISSION_SYNC_PUB], 'on' => self::SCENARIO_UPDATE],

8、在浏览器中打开网址:http://www.channel-pub-api-localhost.chinamcloud.com/weibo-oauth2/authorize-update?group_id=spider&channel_app_source_uuid=269f68bc098011e9b1c354ee75d2ebc1&user_name=华栖云1658397962&permission=&status=1&redirect_uri=aHR0cDovL3d3dy56bXQuY29tLw%3D%3D ,permission 的值为 空字符串,此时验证规则生效,但是其值已经从字符串变化为 0,期望的是,当其值非“空值”时,才转换整数值,如图3

图3

9、默认情况下,当输入项为空字符串,空数组,或 null 时,会被视为“空值”。在 核心验证器 之中,filter(滤镜)验证器默认会处理空输入。调整 filter(滤镜)验证器,其 yii\base\Validator::skipOnEmpty 属性为 false,调整为 true

            /* 更新微博的微连接的网页应用的用户 */   [['permission', 'status'], 'filter', 'filter' => 'intval', 'skipOnEmpty' => true, 'on' => self::SCENARIO_UPDATE],
            [['permission'], 'in', 'range' => [self::PERMISSION_SYNC, self::PERMISSION_PUB, self::PERMISSION_SYNC_PUB], 'on' => self::SCENARIO_UPDATE],

10、在浏览器中打开网址:http://www.channel-pub-api-localhost.chinamcloud.com/weibo-oauth2/authorize-update?group_id=spider&channel_app_source_uuid=269f68bc098011e9b1c354ee75d2ebc1&user_name=华栖云1658397962&permission=&status=1&redirect_uri=aHR0cDovL3d3dy56bXQuY29tLw%3D%3D ,permission 的值为 空字符串,此时验证规则生效,数据验证失败:权限不能为空。如图4

图4

11、此时,2 条规则的顺序可以随意调整了,因为 2 条规则皆是在其值非“空值”时,才会执行验证,推荐置于最后,表示当验证通过后,才转为整数值

            /* 更新微博的微连接的网页应用的用户 */            [['permission'], 'in', 'range' => [self::PERMISSION_SYNC, self::PERMISSION_PUB, self::PERMISSION_SYNC_PUB], 'on' => self::SCENARIO_UPDATE],
   [['permission', 'status'], 'filter', 'filter' => 'intval', 'skipOnEmpty' => true, 'on' => self::SCENARIO_UPDATE],

12、在浏览器中打开网址:http://www.channel-pub-api-localhost.chinamcloud.com/weibo-oauth2/authorize-update?group_id=spider&channel_app_source_uuid=269f68bc098011e9b1c354ee75d2ebc1&user_name=华栖云1658397962&permission=&status=1&redirect_uri=aHR0cDovL3d3dy56bXQuY29tLw%3D%3D ,permission 的值为 空字符串,此时验证规则生效,数据验证失败:权限不能为空。与步骤 10 的异常响应一致,符合预期

 

永夜