关于sql:PHP Prepared Statement vs mysqli_real_escape_string

PHP Prepared Statement vs mysqli_real_escape_string

本问题已经有最佳答案,请猛点这里访问。

我在下面写了一些代码。我想知道两件事。

1。我的代码有漏洞吗?

2。我需要使用mysqli_real_escape_字符串和准备好的语句吗?它是作为额外的安全层还是冗余的?

使用的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
$admin_type = mysqli_real_escape_string($conn, $_POST['admin_type']);
$position = mysqli_real_escape_string($conn, $_POST['position']);
$first_name = mysqli_real_escape_string($conn, $_POST['first_name']);
$last_name = mysqli_real_escape_string($conn, $_POST['last_name']);
$user_name = mysqli_real_escape_string($conn, $_POST['user_name']);
$email = mysqli_real_escape_string($conn, $_POST['email']);
$phone_number = mysqli_real_escape_string($conn, $_POST['phone_number']);
$passwd = mysqli_real_escape_string($conn, $_POST['passwd']);
$created_at = mysqli_real_escape_string($conn, $_POST['created_at']);
$about = mysqli_real_escape_string($conn, $_POST['about']);

$sql ="INSERT INTO admin_accounts (admin_type, position, first_name, last_name, user_name, email, phone_number, passwd, about) VALUES (?,?,?,?,?,?,?,?,?);";

$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)) {
    echo"SQL Error";
} else {
    mysqli_stmt_bind_param($stmt,"sssssssss", $admin_type, $position, $first_name, $last_name, $user_name, $email, $phone_number, $passwd, $about);
    mysqli_stmt_execute($stmt);
  {
        $_SESSION['success'] ="Admin user added successfully!";
        header('location: admin_users');
        exit();
    }    
}
   
}


虽然php-prepared语句和php-mysqli-real-escape-string都有相同的目标,即试图以may不会对数据库造成损害的格式获取字符串或用户输入,但这两个古老的参数都不能执行相同的功能。我使用了may一词,因为缺乏适当的验证仍然会导致相同的问题。莱姆斯

例如,一个删除查询,要求用户在没有适当验证的情况下删除自己的日志,用户可能会删除其他用户的日志,而用户甚至不需要SQL注入来存档这些日志。

1
string mysqli_real_escape_string ( mysqli $link , string $escapestr )

此函数用于创建可在SQL语句中使用的合法SQL字符串。给定的字符串被编码为转义的SQL字符串,考虑到current character set of the connection,这意味着mysqli_real_escape_字符串依赖于当前的字符集。

虽然准备好的语句将您的值/用户输入绑定到特定的Data type上,并指示您的SQL将其视为这样,但这也取决于您指定的数据类型。

基本上,mysqli_real_escape_字符串将根据定义的字符集清除用户输入中的垃圾,而准备好的语句将确保用户输入中是否存在垃圾,它将被解释为您希望它被解释为通常是用户垃圾:)

我想说的是,使用这两者不是一个坏主意,但保护您的数据库是您的开发者采取一切必要的和合乎逻辑的步骤,以存档最大的安全没有人关心的黑客网站有多快!!


对于使用查询参数而言,转义是多余的。如果同时使用绑定查询参数,则不要使用转义。最后,您将得到数据库中的数据,其中包含文字反斜杠。

只需使用查询参数。绑定参数比所有对mysqli_real_escape_string()的调用都简单易行。

更简单的是使用PDO,因为您甚至不需要进行绑定。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{  
    $param_keys = ['admin_type'=>null, 'position'=>null, 'first_name'=>null,
        'last_name'=>null, 'user_name'=>null, 'email'=>null, 'phone_number'=>null,
        'passwd'=>null, 'created_at'=>null, 'about'=>null];

    // make sure the params include all keys in $param_keys,
    // but no keys that aren't in $param_keys
    $params = array_merge($param_keys, array_intersect_key($_POST, $param_keys));

    $sql ="
        INSERT INTO admin_accounts
        SET admin_type = :admin_type,
            position = :position,
            first_name = :first_name,
            last_name = :last_name,
            user_name = :user_name,
            email = :email,
            phone_number = :phone_number,
            passwd = :passwd,
            about = :about"
;

    $stmt = $pdoConn->prepare($sql);
    $stmt->execute($params);
    $_SESSION['success'] ="Admin user added successfully!";
    header('location: admin_users');
}

我假设您将PDO配置为在出错时抛出异常。