改进聚合查询的安全性

This commit is contained in:
thinkphp
2018-10-18 18:37:53 +08:00
parent 898fe001c2
commit 8652c83ea1
4 changed files with 39 additions and 5 deletions

View File

@@ -98,6 +98,10 @@ abstract class Builder
$result = [];
foreach ($data as $key => $val) {
if ('*' != $options['field'] && !in_array($key, $fields, true)) {
continue;
}
$item = $this->parseKey($key, $options, true);
if ($val instanceof Expression) {
$result[$item] = $val->getValue();

View File

@@ -531,13 +531,36 @@ class Query
public function count($field = '*')
{
if (isset($this->options['group'])) {
if (!preg_match('/^[\w\.\*]+$/', $field)) {
throw new Exception('not support data:' . $field);
}
// 支持GROUP
$options = $this->getOptions();
$subSql = $this->options($options)->field('count(' . $field . ')')->bind($this->bind)->buildSql();
return $this->table([$subSql => '_group_count_'])->value('COUNT(*) AS tp_count', 0, true);
}
return $this->value('COUNT(' . $field . ') AS tp_count', 0, true);
return $this->aggregate('COUNT', $field, true);
}
/**
* 聚合查询
* @access public
* @param string $aggregate 聚合方法
* @param string $field 字段名
* @param bool $force 强制转为数字类型
* @return mixed
*/
public function aggregate($aggregate, $field, $force = false)
{
if (!preg_match('/^[\w\.\*]+$/', $field)) {
throw new Exception('not support data:' . $field);
}
$result = $this->value($aggregate . '(' . $field . ') AS tp_' . strtolower($aggregate), 0, $force);
return $result;
}
/**
@@ -548,7 +571,7 @@ class Query
*/
public function sum($field)
{
return $this->value('SUM(' . $field . ') AS tp_sum', 0, true);
return $this->aggregate('SUM', $field, true);
}
/**
@@ -560,7 +583,7 @@ class Query
*/
public function min($field, $force = true)
{
return $this->value('MIN(' . $field . ') AS tp_min', 0, $force);
return $this->aggregate('MIN', $field, $force);
}
/**
@@ -572,7 +595,7 @@ class Query
*/
public function max($field, $force = true)
{
return $this->value('MAX(' . $field . ') AS tp_max', 0, $force);
return $this->aggregate('MAX', $field, $force);
}
/**
@@ -583,7 +606,7 @@ class Query
*/
public function avg($field)
{
return $this->value('AVG(' . $field . ') AS tp_avg', 0, true);
return $this->aggregate('AVG', $field, true);
}
/**

View File

@@ -109,6 +109,9 @@ class Mysql extends Builder
}
}
if ($strict && !preg_match('/^[\w\.\*]+$/', $key)) {
throw new Exception('not support data:' . $key);
}
if ('*' != $key && ($strict || !preg_match('/[,\'\"\*\(\)`.\s]/', $key))) {
$key = '`' . $key . '`';
}

View File

@@ -94,6 +94,10 @@ class Sqlsrv extends Builder
$table = $options['alias'][$table];
}
}
if ($strict && !preg_match('/^[\w\.\*]+$/', $key)) {
throw new Exception('not support data:' . $key);
}
if ('*' != $key && ($strict || !preg_match('/[,\'\"\*\(\)\[.\s]/', $key))) {
$key = '[' . $key . ']';
}