MySQLi和PHP允许表单提交中的特殊字符,但不允许SQL插入?

时间:2015-07-14 19:17:59

标签: php html forms mysqli htmlspecialchars

我一直在编写一个PHP脚本,用于我在网站上使用的“联系我们”表单,以允许用户对该网站发表评论。它有几个字段,包括名称字段和用于注释的文本区域。用户提交表单后,将注释输入到数据库中,然后查询最近的五条注释并将其显示在网站上。但是,用户当前无法在名称字段或注释区域中输入撇号(')并正确显示它们。

这是一系列事件:

"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.
  • 我了解"来自htmlspecialchars函数,并认为\'来自mysqli_real_escape_string()函数。

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

Name with Apostro\'phe
I\'m happy with the "/" and the "" of the present.
  • \'相同。我如何获得它,以便在从数据库中查询撇号正常显示后在HTML中重新显示它?

但是,这不是我想要的。当它显示在评论部分(从数据库中查询后)时,我希望它显示为用户输入的内容。我并不关心它在数据库中的外观,只要它在查询返回HTML时填充列表就能正常显示。

我应该怎么做才能让用户在他们的名字/评论中输入撇号,并在从数据库返回后显示撇号;但与此同时,不会冒SQL注入的风险?我看过几个相关的问题,但没有找到任何能回答我问题的问题。

MySQL/PHP: Allow special characters and avoid SQL injections

  • 我已经尝试过这篇文章中没有成功的方法

php - Allowing special characters in form submit

  • 我不需要这样的东西,只有撇号

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

1 个答案:

答案 0 :(得分:2)

您正在使用带有预处理语句的占位符。手动转义文本完全没必要。数据库已经作为占位符系统的一部分进行了自己的内部转义,因此您的转义只会添加一个额外的转义层,这些转义将输入到表中。

e.g。

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";