【问题标题】:PHP Prepared Statement vs mysqli_real_escape_string [duplicate]PHP Prepared Statement vs mysqli_real_escape_string [重复]
【发布时间】:2019-01-17 12:32:48
【问题描述】:

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

1.我的代码有漏洞吗?

2。我是否需要将 mysqli_real_escape_string 与准备好的语句一起使用?它会充当额外的安全层还是多余的?

使用的代码:

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();
    }     
}
    
}

【问题讨论】:

  • 您的代码仍然为那些嗅探纯文本密码的人敞开大门,并且相对容易找到/弄清楚。如果我是你,我会考虑正确地散列和存储密码,如果你打算上网的话。这些函数称为password_hash(),验证它们的称为password_verify()。在网上查一下;你会得到很多(好的)点击,包括 php.net 上的手册。顺便说一句,我关闭了您可以咨询的问题。
  • 当然,我现在确实在这样做!谢谢你:)
  • 你的意思是我之前在评论中发布的功能?
  • 是的,我正在阅读它!

标签: php sql prepared-statement sql-injection


【解决方案1】:

一个古老的论点,PHP Prepared Statement 和 PHP mysqli_real_escape_string 不执行相同的功能,尽管两者都有相同的目标,即尝试以 may 不会对我使用的数据库造成损害的格式获取字符串或用户输入术语may,因为缺乏适当的验证仍然会导致同样的问题。

以删除查询为例,用户可以在没有适当验证的情况下删除自己的帖子,用户可能会删除其他用户的帖子,用户甚至不需要 SQL 注入来存档。

string mysqli_real_escape_string ( mysqli $link , string $escapestr )

此函数用于创建一个合法的 SQL 字符串,您可以在 SQL 语句中使用它。给定的字符串被编码为转义的 SQL 字符串,考虑到 current character set of the connection 现在这意味着 mysqli_real_escape_string 取决于您当前的字符集。

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

基本上 mysqli_real_escape_string 将根据定义的字符集取出用户输入中的垃圾,而准备好的语句将确保用户输入中是否有任何垃圾,它只会被解释为您希望它被解释,这通常是作为用户垃圾:)

我想说的是,同时使用两者并不是一个坏主意,但保护您的数据库的责任在于开发人员采取一切必要和合乎逻辑的步骤来存档最大的安全性没有人关心被黑客入侵的网站有多快!!

【讨论】:

  • 完美答案!非常感谢
【解决方案2】:

转义对于使用查询参数是多余的。如果您还使用绑定查询参数,请不要使用转义。您最终会得到数据库中包含文字反斜杠的数据。

只需使用查询参数。绑定参数比所有那些对mysqli_real_escape_string() 的调用更容易和简单。

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

例子:

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');
}   

我假设你是configured PDO to throw exceptions on error

【讨论】:

  • 完美谢谢!我会等着的:)
  • 未定义变量:第 36 行 C:\xampp\htdocs\test\add_admin.php 中的 pdoConn
  • 我似乎遇到了上述错误
  • 顺便说一句,我没有将 PDO 配置为在错误时引发异常。我之前实际上从未使用过 PDO
  • 非常感谢,感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多