Php 用户输入,在发送到db之前进行清洁和消毒

Php 用户输入,在发送到db之前进行清洁和消毒,php,html,mysql,Php,Html,Mysql,我在这里搜索了很多问题,发现它们要么非常古老,要么建议使用预先准备好的语句PDO,而我没有使用。所以我需要你的帮助 我有一个小的讨论/聊天框,用户可以在其中使用 我需要的是清理和过滤用户输入,使其只接受纯文本(例如,无标记、无html标记、无脚本、无链接等)同样,允许换行非常重要 根据我的阅读,我按照以下顺序做了以下工作: trim() htmlentities($comment,ENT\u NOQUOTES) mysqli\u real\u escape\u string() nl2br()

我在这里搜索了很多问题,发现它们要么非常古老,要么建议使用预先准备好的语句PDO,而我没有使用。所以我需要你的帮助

我有一个小的讨论/聊天框,用户可以在其中使用

我需要的是清理和过滤用户输入,使其只接受纯文本(例如,无标记、无html标记、无脚本、无链接等)同样,允许换行非常重要

根据我的阅读,我按照以下顺序做了以下工作:

  • trim()
  • htmlentities($comment,ENT\u NOQUOTES)
  • mysqli\u real\u escape\u string()
  • nl2br()
  • 我现在做的是对的吗?或者我错过了什么

    还有
    从数据库回送数据时,我需要做什么


    真的,谢谢你的帮助和好意

    你还有另一个选择。您可以将准备好的语句与
    mysqli

    它们学习起来并不困难,而且比
    mysqli\u real\u escape\u string()
    好一点,因为您不必担心转义查询中的每个变量。它们在进入数据库之前本质上是“准备好的”。这样做还有其他好处,即:

  • 您不需要
    addslashes()
    就可以使用 撇号等

  • 对于大型数据库,它们将大大加快速度 升级您的查询(很像PDO)

  • 以下是如何做到这一点:

    通过创建新的mysqli对象连接到数据库,如下所示:

    $conn = new mysqli($host, $username, $password, $dbname);
    
    if ($conn->connect_error) {
        die("Connection failed: " . $dbc->connect_error);
        }
    
    <input type="text" name="var1">
    
    $stmt= $conn->prepare("insert into tablename (key1, key2) values (?,?)");
    $stmt->bind_param("is",$var1, $var2);
    $stmt->execute();
    $stmt->close();
    
    接下来,您要转换表单中的变量

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

    $conn = new mysqli($host, $username, $password, $dbname);
    
    if ($conn->connect_error) {
        die("Connection failed: " . $dbc->connect_error);
        }
    
    <input type="text" name="var1">
    
    $stmt= $conn->prepare("insert into tablename (key1, key2) values (?,?)");
    $stmt->bind_param("is",$var1, $var2);
    $stmt->execute();
    $stmt->close();
    
    然后,您可以创建如下事务:

    $conn = new mysqli($host, $username, $password, $dbname);
    
    if ($conn->connect_error) {
        die("Connection failed: " . $dbc->connect_error);
        }
    
    <input type="text" name="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->fetch();
    
    或者如果查询返回多行

    while ($stmt->fetch() {
        echo $var1 . $var2;
    }
    
    nl2br()
    用于输出,无需担心输入;它可以作为
    \n
    存储在数据库中,当您需要时,它会以中断的形式吐出。如果其中一个变量需要将新行转换为

    标记,您可以按照建议在变量上使用
    nl2br()
    (注意,这不会增加安全性,但正如您所说,您需要它),如下所示


    你也可以在这个问题上使用
    trim()
    htmlentities()
    ,如果它被回送到表单输入字段中,并且如果输出中有html字符,你不希望表单中断。

    你的问题可以引导我构建一个具有许多功能的完整项目;)哈哈

    在开始执行out步骤之前,我们需要一个用于此场景的虚拟(测试)数据库。我们调用数据库聊天盒,其中的表名为chat。您只需在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();
    }
    
    <?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;
    }
    
    此文件包含一个函数,用于清理或过滤输入内容中的注释或其他输入。以及影响数据视图的过滤器输出

    所有这些都取决于您的策略和您的需要,例如,如果您需要允许人们发布url或电子邮件地址,url和电子邮件是否应成为活动链接或仅作为文本查看等。这样,您可以定义哪些过滤器应用于您的内容输入,哪些过滤器应用于您的内容输出

    您可以向函数添加或删除额外功能。文本输入和输出有很多特性,您可以单独测试和评估这些特性,甚至可以扩展过滤函数或创建自己的函数

    最后一步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语句作为示例和筛选函数。您可以进行测试,以您喜欢的方式扩展它,或者进一步开发您自己的项目

    下面是我制作的聊天室示例的屏幕截图:

    首先,保持文本逻辑清晰:

    trim() -- OK
    htmlentities($comment, ENT_NOQUOTES)  -- No; do later
    mysqli_real_escape_string()  -- Yes; required by API
    nl2br()  -- No; see below
    
    这些建议背后的逻辑是:数据库中的数据应该只是普通数据。不是htmlentities,不是br标记。但是,为了将数据从PHP传递到MySQL,必须执行escape_字符串;逃逸物品将不会被储存

    但是。。。这只是中间的一步。这些数据来自哪里?旧版本的PHP试图“保护”您添加的转义码和其他垃圾对HTML正常工作,但破坏了MySQL。关闭这种神奇的转义,获取原始数据

    数据去哪里了?可能是HTML?
    选择
    从表中返回数据后,首先执行
    htmlentities()
    和(可选)
    nl2br()

    注意,如果您希望保留像
    (斜体)这样的内容,那么您就是在自找麻烦——大麻烦。黑客所需要做的就是将各种各样的污点注入你的网页,甚至整个系统。

    可能是你正在寻找的另一个污点。