【发布时间】:2019-02-07 11:54:19
【问题描述】:
我用函数 query() 创建了这个类:
这个函数使得使用准备好的语句变得非常容易。 但是
- 安全吗?
- 这样使用它更有意义吗?
我已经用sqlmap 测试过了,看起来不错。
该函数基本上将普通的 SELECT 字符串拆分为多个较小的字符串以检测输入值。 它保存输入值和字符串本身。 字符串本身将被 ? 替换。 比正常的准备功能取代 ?再次输入值。
class dbcon
{
public $con;
public function __construct()
{
$this->con = new mysqli( $host, $username, $password, $dbname );
}
public function query( $query )
{
//selcet
if( strpos( $query, "SELECT" ) !== false )
{
$types = ""; $to_replace = []; $values = [];
$query = explode( "WHERE", $query );
$query_where = explode( "ORDER BY", $query[ '1' ] );
$query_where[ '0' ];
if( isset( $query_where[ '1' ] ) )
{
$ORDERBY = explode("LIMIT", $query_where[ '1' ]);
}
if( isset( $ORDERBY[ '1' ] ) )
{
$LIMIT = $ORDERBY[ '1' ];
}
$SELECT = $query[ '0' ];
$where = str_replace( array( "(", ")", "[", "]" ), "", $query_where[ '0' ] );
$where = str_replace( array( "AND", "OR", "and", "or" ), "-|-", $where );
$where = explode( "-|-", $where );
for ($i=0; $i < count($where); $i++) {
$for_where = str_replace( array( "!=", "<=", ">=", "=", "<>", ">", "<", "IS", "NOT LIKE", "LIKE" ), "#|#", $where[ $i ] );
$for_where = explode( "#|#", $for_where );
$value = trim( $for_where[ '1' ] );
if( substr_count($value, "AND") <= 0 AND substr_count($value, "OR") <= 0 )
{
$value = "'?'";
}
$to_replace[] = $value;
$value_num = "values".$i;
$$value_num = $value;
$values[] = &$$value_num;
$types .= "s";
}
$WHERE = str_replace( $to_replace , " ? ", $query_where[ '0' ] );
$prepare = $SELECT . " WHERE " . $WHERE;
if ( isset( $ORDERBY ) )
{
$prepare .= " ORDER BY " . $ORDERBY[ '0' ];
}
if ( isset( $LIMIT ) ){
$prepare .= " LIMIT " . $LIMIT;
}
$stmt = $this->con->prepare( $prepare );
//$stmt->bind_param($types, $values['0'],$values['1']);
call_user_func_array( array( $stmt, "bind_param" ), array_merge( array( $types ), $values ) );
$stmt->execute();
return $stmt->get_result();
$stmt->close();
}
}
}
$db = new dbcon();
调用函数:
$id = $_GET[ 'id' ];
$my_query = $db->query("SELECT * FROM Users WHERE ID = '$id' ORDER BY created DESC");
while($row = $my_query->fetch_array()){
echo $row['NAME']."<br>";
}
更新:
旧功能没有多大意义,根本不安全。这应该仍然是一个简单的方法,但更好。
public function query( $query, $types, $query_values )
{
$values = [];
for ($i=0; $i < count($query_values); $i++) {
$value_num = "values".$i;
$$value_num = $query_values[ $i ];
$values[] = &$$value_num;
}
$stmt = $this->con->prepare( $query );
call_user_func_array( array( $stmt, "bind_param" ), array_merge( array( $types ), $values ) );
$stmt->execute();
return $stmt->get_result();
$stmt->close();
}
调用函数
$query = "SELECT * FROM _Users WHERE ID = ? ORDER BY created ASC";
$my_query = $db->query( $query, "s", array( $id ) );
while($row = $my_query->fetch_array()){
echo $row['title']."<br>";
}
【问题讨论】:
-
您希望我们回答哪个问题;标题中的那个,还是正文中的那个?
-
只是……为什么要这样做?为什么不提供一个接受参数化查询的查询方法以及要绑定的对象数组?
-
这属于代码审查网站。
-
@SilvanFux
Make it even sense to use it like that?- 没有。 -
这是我所见过的最复杂的代码,无法实现任何目标
标签: php mysql mysqli prepared-statement