我的SQLi 和 PHP 允许在表单提交中使用特殊字符,但 SQL 不允许插入?

MySQLi and PHP allow special characters in form submission, but not SQL insert?

我一直在为网站上使用的 "Contact Us" 表单编写 PHP 脚本,以允许用户对网站发表评论。它有几个字段,包括一个名称字段和一个用于注释的文本区域。用户提交表单后,评论被输入数据库,然后查询最近的五个评论并将它们显示在网站上。但是,用户目前无法在名称字段或评论区域中输入apostrophes (') 并使其正常显示。

这是事件的顺序:

"User Submit -> Prepare SQL -> Insert Record -> Query Database -> Return recent Comments"

目前,这就是我 PHP:

//Function that will trim the input, and run it through a small security check
function test_input($input)
{
    $input = trim($input);
    $input = stripslashes($input);
    $input = htmlspecialchars($input);
    return $input;
}

$name = test_input($_POST["txtName"]);
$comments = test_input($_POST["txtComments"]);

//Prepared statement to insert a new Contact record
$stmt = $conn -> prepare("INSERT INTO tableName (name, comments) VALUES (?, ?)");

//Create the parameters of the prepared statement
$stmt -> bind_param("ss", $param_name, $param_comments);

//Set the parameters of the statement, running them through a security check
$param_name = mysqli_real_escape_string($conn, $name);
$param_comments = mysqli_real_escape_string($conn, $comments);

//Execute the prepared statement
$stmt -> execute()

如您所见,我正在 运行 通过 htmlspecialchars() 函数和 mysqli_real_escape_string() 函数设置变量。但是,当我 运行 函数时,我仍然得到一个奇怪的输出。


输入

Name with Apostro'phe
I'm happy with the "/" and "\" of the present.

它看起来如何...

...数据库

Name with Apostro\'phe
I\'m happy with the "/" and the "" of the present.

..网站评论部分(从数据库填充)

Name with Apostro\'phe
I\'m happy with the "/" and the "" of the present.

然而,这不是我想要的。当它显示在评论部分时(从数据库中查询后),我希望它显示为用户输入的内容。我真的不在乎它在数据库中的外观,只要它在查询返回 HTML 以填充列表时正确显示即可。


我应该怎么做才能让用户在他们的 name/comments 中输入 apostrophes,并在从数据库返回后显示出来;但同时,没有运行被SQL注入的风险?我查看了几个相关问题,但没有找到任何可以回答我问题的内容。

MySQL/PHP: Allow special characters and avoid SQL injections

php - Allowing special characters in form submit

如果我需要澄清任何事情,请告诉我!

您在准备好的语句中使用了占位符。完全没有必要手动转义文本。作为占位符系统的一部分,数据库已经在进行自己的内部转义,因此您的转义只是添加了一个额外的转义层,这些转义层将进入 table.

例如

name                   = "Miles O'Brien";
manual escape         -> "Miles O\'Brien";
placeholder escape    -> "Miles O\'Brien";
stored in database    -> "Miles O\'Brien";
retrieved from db     -> "Miles O\'Brien";
displayed to user     -> "Miles O\'Brien";

如果您删除手动转义,那么突然之间一切都会按预期运行:

name                   = "Miles O'Brien";
placeholder escape    -> "Miles O\'Brien";
stored in database    -> "Miles O'Brien";
retrieved from db     -> "Miles O'Brien";
displayed to user     -> "Miles O'Brien";