用户输入,在发送到db之前清理并清理

时间:2015-08-09 16:18:33

标签: php html mysql

我在这里搜索了很多问题,我发现他们要么已经很老了,要么建议使用准备好的语句 PDO 我不使用< / strong>即可。所以我需要你的帮助。

我有一个小型讨论/聊天框,用户使用<textarea>

提交消息

我需要清理和过滤用户输入,因此它只接受纯文本(例如没有标签,没有html标签,没有脚本没有链接等)。 同样,允许换行符很重要。

根据我的阅读,我按以下顺序进行以下操作:

  1. trim()
  2. htmlentities($comment, ENT_NOQUOTES)
  3. mysqli_real_escape_string()
  4. nl2br()
  5. 我正在做的是对的吗?或者我错过了什么?

    echo来自数据库的数据时,我还需要做什么吗?

    真的,感谢你的帮助和善意

5 个答案:

答案 0 :(得分:8)

首先,保持文本的逻辑和清洁:

trim() -- OK
htmlentities($comment, ENT_NOQUOTES)  -- No; do later
mysqli_real_escape_string()  -- Yes; required by API
nl2br()  -- No; see below

这些建议背后的逻辑:数据库中的数据应该只是普通数据。不是htmlentities,不是br-tags。但是,您必须执行escape_string才能将数据从PHP传递到MySQL;逃跑不会被存储。

但是......这只是中间步骤。数据来自哪里?较旧版本的PHP试图&#34;保护&#34;你要添加转义和其他适用于HTML的垃圾,但搞砸了MySQL。关闭这样的魔法转义,并获取原始数据。

数据去哪儿了?可能是HTML?在SELECTing数据退出表格后,然后首先执行htmlentities()和(可选)nl2br();

注意,如果您希望保留<I>(用于斜体)之类的内容,那么您就会遇到麻烦 - 大麻烦。黑客需要做的就是<script> ...向你的网页和整个系统注入各种各样的肮脏。

答案 1 :(得分:6)

您还有其他选择。您可以将准备好的语句与mysqli

一起使用

它们的学习和工作并不比mysqli_real_escape_string()好一点,因为您无需担心转义查询中的每个变量。在进入数据库之前,它们本质上是“准备好的”。还有其他优点,其中包括:

  1. 您无需addslashes()即可处理字符 撇号等。

  2. 对于大型数据库,它们会相当快 你的查询(很像PDO)。

  3. 以下是如何操作:

    通过创建一个新的mysqli对象连接到数据库:

    $conn = new mysqli($host, $username, $password, $dbname);
    
    if ($conn->connect_error) {
        die("Connection failed: " . $dbc->connect_error);
        }
    

    接下来,您要从表单转换变量。

    假设你有一个这样的表单字段:

    <input type="text" name="var1">
    

    你可以像这样使用htmlentities和trim,并创建你的$var1变量:

    $var1 = htmlentities(trim($_POST['var1']));
    

    然后您可以像这样创建交易:

    $stmt= $conn->prepare("insert into tablename (key1, key2) values (?,?)");
    $stmt->bind_param("is",$var1, $var2);
    $stmt->execute();
    $stmt->close();
    

    基本上就是这样。您可以像往常一样进行查询,而是使用?占位符,分配数据类型(上面是i表示整数,s表示字符串)然后将它们绑定到您的查询中的占位符。

    基本上就是这样。

    如果你想用带变量的select来做,你可以使用普通的select语法和?与变量相同的方式,然后绑定它。然后,您可以轻松地将结果绑定到变量中(假设var3是一个整数):

    $stmt= $conn->prepare("select var1, var2  from tablename where var3 = ?");
    $stmt = bind_param("i", $var3);
    $stmt->bind_result($var1, $var2);
    $stmt->execute();
    $stmt->close()
    

    然后您可以使用此

    获取变量
    $stmt->fetch();
    

    或者如果您的查询带回多行

    while ($stmt->fetch() {
        echo $var1 . $var2;
    }
    

    nl2br()用于输出,您无需担心输入;它可以作为\n存储在数据库中,并在需要时将其作为中断吐出。如果其中一个变量需要将新行转换为<br/>标记,您可以建议在变量上使用nl2br()(注意这不会增加安全性,但正如您所说,您需要它),就像所以

    echo nl2br($var1, false);
    

    如果它被回显到表单输入字段中,你也可以使用trim()htmlentities(),如果有html字符,你不希望你的表单中断输出

答案 2 :(得分:3)

你的问题可以让我建立一个包含许多功能的完整项目;)lol

在我们开始执行步骤之前,我们需要一个用于此场景的虚拟(测试)数据库。我们用称为聊天的表呼叫数据库聊天箱。您可以通过在MySQL测试环境中执行以下sql语句来创建它:

CREATE TABLE `chat` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `msg` VARCHAR(200) NOT NULL DEFAULT '0',
    `user_id` INT(11) NULL DEFAULT '0',
    PRIMARY KEY (`id`)
)
ENGINE=InnoDB
;

现在你可以按照这里的步骤进行操作:

步骤1:在Web服务器中创建项目文件夹。 基于PDO构建数据库连接并将其命名为dbConnect.inc.php

<?php
// check if PDO driver not available
if (!defined('PDO::ATTR_DRIVER_NAME'))
    echo 'PDO driver unavailable <br />';

// database configuration
$dbHost = "localhost";
$dbPort = "3306";
$dbName = "chatbox";
$dbUser = "root";
$dbPass = "";
$strDSN = "mysql:host=$dbHost:$dbPort;dbname=$dbName";

// database connection
try
{
    $dbConn = new PDO($strDSN, $dbUser, $dbPass);
    //Activate following line to view all error messages 
    $dbConn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e)
{
    die("Could not connect to the database $dbName, error info: <br />"
        . $e->getMessage());
    exit();
}

在进入下一步之前,我将测试这项工作。顺便说一下,准备好的方法不需要mysqli_real_escape_string()

我使用PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION代替if语句,这个方法会在开发项目时为您提供有用的错误详细信息。在项目的开发过程中,您将找到哪种方法更适用于获取错误消息。

第2步:创建文件调用filter.inc.php

<?php
// filter for input
function filterInput($content)
{
    $content = trim($content);
    $content = stripslashes($content);

    return $content;
}

//filter for viewing data
function filterOutput($content)
{
    $content = htmlentities($content, ENT_NOQUOTES);
    $content = nl2br($content, false);

    return $content;
}

此文件包含一个filterInput函数,用于清理或过滤输入内容以供注释或其他输入。以及影响数据视图的filterOutput

所有这些都取决于您的策略和您需要的内容,例如,如果您需要允许人们发布网址或电子邮件地址,请将网址和电子邮件设置为活动链接或仅查看为文本等,以便您可以定义应使用哪个过滤器对于您的内容输入以及应该为您的内容输出使用哪个过滤器。

您可以为功能添加或删除其他功能。文本输入和输出有许多功能,您可以单独测试它们并对其进行评估,甚至可以扩展过滤功能或创建自己的功能。

最后一步3:现在我们将这些谜题放在index.php文件中:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Chat box</title>
</head>

<body>
<?php include './dbConnect.inc.php'; ?>
<?php include './filter.inc.php'; ?>

<h1>Chat box</h1>

<p>
    <?php
    // this is dummy user id, but use the id over user id when login or the way you want
    // this is only example
    $user_id = 1;

    if (isset($_POST["msg"]))
    {
        $msg = filterInput($_POST["msg"]);
        $sql = "INSERT INTO chat "
            . "(msg, user_id) "
            . "VALUES "
            . "(:msg, :user_id)";

        $stmt = $dbConn->prepare($sql);
        $fieldsArr = [':msg' => $msg, ':user_id' => $user_id];
        $stmt->execute($fieldsArr)
        // refresh page after insert
        header("Location: " . $_SERVER['REQUEST_URI']);
    }
    ?>

<form action="index.php" method="post">
    <textarea name="msg" id="msg" required></textarea>
    <input name="submit" type="submit">
</form>
</p>

<p>Comments</p>

<p>
    <?php
    $sql = "SELECT * FROM chat WHERE user_id = (:user_id);";
    $stmt = $dbConn->prepare($sql);
    $fieldsArr = [':user_id' => $user_id];
    $stmt->execute($fieldsArr)

    while ($result = $stmt->fetch())
        echo "<h3>" . filterOutput($result['msg']) . "</h3>";

    $dbConn = null;
    ?>
</p>

</body>
</html>

这是为了证明事情是如何运作的。您有insert,select语句作为示例和过滤函数。您可以按照自己喜欢的方式进行测试或扩展,或者进一步开发自己的项目。

以下是我制作的聊天室示例的屏幕截图: enter image description here

答案 3 :(得分:0)

filter_input可能是您正在寻找的另一个。它可以节省您编写清理和验证代码的时间。当然,它并没有涵盖每一个案例,但足够多,以便您可以更专注于特定的过滤/验证代码。

  

虽然强烈建议使用预备语句   PDO / mysqli的。但有时转换整体并不容易   项目的尾端项目。你应该学习PDO / mysqli   你的下一个项目。

$comment = filter_input(INPUT_POST, 'comment', FILTER_SANITIZE_STRING);

您有不同的Types of filters。您可以根据需要进行选择。您还可以使用filter_has_var检查变量集。

答案 4 :(得分:-2)

你的代码看起来很好,如果你不想准备语句,那么逃避是下一个最好的事情。当你回应时它应该是直截了当的,它只是纯文本。