没有绑定参数的mysql预处理语句仍然是安全的


mysqli prepared statement without binding parameters still secure?

这是我在这里的第一篇文章,我对编程的世界也比较陌生。简而言之,在总结我的电子商务网站时,使用php, mysql和javascript/jquery开发,我发现我构建所有查询的方式(使用mysql_connect)可能导致mysql注入和许多其他讨厌的事情。

试图"转换"一切更安全的我自己准备的语句方式,我写了一个类包含所有的方法,我需要从我的数据库检索信息,但我不确定的方式,我正在进行查询。

类的构造函数
class Database {
    private $DBH;
    public function __construct() {
        $this->DBH = new mysqli(WEB_SERVER, WEB_USER, WEB_PASS, WEB_NAME);
        if ($this->DBH->connect_errno) {
            return "Failed to connect to MySQL: (" . $this->DBH->connect_errno . ") " . $this->DBH->connect_error;
            exit();
        }
    }
    ...
}

…还有一个查询示例:

public function get_record_by_param($record, $param, $value) {
    $stmt = $this->getDBH()->stmt_init();
    $query = "SELECT * ";
    $query .= "FROM {$record} ";
    $query .= "WHERE {$param} = {$value} LIMIT 1";
    if($stmt->prepare($query)){
        return $this->execute_simpleAssoc($stmt);
    } else {
    return "Prepare failed: (" . $this->getDBH()->errno . ") " . $this->getDBH()->error;
    }
}

使用这样的查询仍然是安全的吗?还是必须使用bind_param方法?

希望我没有混淆,谢谢你的任何建议。

不,它不安全。mysql无法解析你的查询字符串中哪些是(潜在的)数据,哪些不是。

如果您希望转义数据,则需要分别绑定每个参数。

但是,绑定参数只对data有效。对于列名,您需要应用白名单,正如@Michael在他的评论中指出的那样。没有办法自动转义列/表名。

适用于所有数据库层,包括PDO。如果向层提供一个完整的查询字符串,其中的数据将被神奇地转义而不是

这更像是一个术语问题。看,有

  • 在查询
  • 中表示数据的占位符的一般概念
  • 预处理语句,它是占位符
  • 的子集。
  • 一个绑定的东西,属于准备好的语句,但是可以省略

"绑定"很可能是指准备好的语句。在这种情况下,答案可能有所不同。
但是你采用占位符的想法,答案会改变:
你运行查询的方式当然是不安全的。
但是,没有(手动)绑定也可以拥有完全安全的查询。
所以,bind_param不是必需的。