Php 用户输入,在发送到db之前进行清洁和消毒
我在这里搜索了很多问题,发现它们要么非常古老,要么建议使用预先准备好的语句PDO,而我没有使用。所以我需要你的帮助 我有一个小的讨论/聊天框,用户可以在其中使用Php 用户输入,在发送到db之前进行清洁和消毒,php,html,mysql,Php,Html,Mysql,我在这里搜索了很多问题,发现它们要么非常古老,要么建议使用预先准备好的语句PDO,而我没有使用。所以我需要你的帮助 我有一个小的讨论/聊天框,用户可以在其中使用 我需要的是清理和过滤用户输入,使其只接受纯文本(例如,无标记、无html标记、无脚本、无链接等)同样,允许换行非常重要 根据我的阅读,我按照以下顺序做了以下工作: trim() htmlentities($comment,ENT\u NOQUOTES) mysqli\u real\u escape\u string() nl2br()
我需要的是清理和过滤用户输入,使其只接受纯文本(例如,无标记、无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()
注意,如果您希望保留像
(斜体)这样的内容,那么您就是在自找麻烦——大麻烦。黑客所需要做的就是将各种各样的污点注入你的网页,甚至整个系统。可能是你正在寻找的另一个污点。