验证和清理表单数据后是不是需要“my_real_escape_string”? [复制]

Posted

技术标签:

【中文标题】验证和清理表单数据后是不是需要“my_real_escape_string”? [复制]【英文标题】:Is 'my_real_escape_string' required after I validated and sanitized form data? [duplicate]验证和清理表单数据后是否需要“my_real_escape_string”? [复制] 【发布时间】:2014-01-16 08:14:36 【问题描述】:

所以我已经在同一个文档中验证并清理了我的表单数据。在我开始看到有关 'my_real_escape_string' 的东西之前,我一直认为它是安全的。

我认为,如果我按自己的方式输入数据,我的数据将是安全的,但我不想冒险。所以我的问题是我是否需要使用这个'my_real_escape_string' 来确保数据安全。

我正在使用下面的代码。首先将是表单文档 (index.php) 本身,然后处理 document(processform.php)。感谢您的所有帮助。

//index.php

<?php
// define variables and set to empty values
$first_nameErr = $last_nameErr = $emailErr = $passwordErr = $genderErr = "";
$first_name = $last_name = $email = $password = $gender = "";

if ($_SERVER["REQUEST_METHOD"] == "POST")

if (empty($_POST["first_name"]))
 $first_nameErr = "";
else
 
 $first_name = test_input($_POST["first_name"]);
 // check if name only contains letters and whitespace
 if (!preg_match("/^[a-zA-Z ]*$/",$first_name))
   
   $first_nameErr = "Only letters allowed";
   
  

if (empty($_POST["last_name"]))
 $last_nameErr = "";
else
 
 $last_name = test_input($_POST["last_name"]);
 // check if name only contains letters and whitespace
if (!preg_match("/^[a-zA-Z ]*$/",$last_name))
   
   $last_nameErr = "Only letters allowed";
   
 


if (empty($_POST["email"]))
  $emailErr = "";
else
 
 $email = test_input($_POST["email"]);
 // check if e-mail address syntax is valid
if (!preg_match("/([\w\-]+\@[\w\-]+\.[\w\-]+)/",$email))
   
   $emailErr = "Invalid email format";
   
  


if (empty($_POST["password"]))
 $passwordErr = "";
else
 $password = test_input($_POST["password"]);

if (empty($_POST["gender"]))
 $genderErr = "";
else
 $gender = test_input($_POST["gender"]);



function test_input($data)

$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;

?>



<div class="signupitsfree" float="right">
<p class="signup">Sign Up<br />It's Completely Free!</p>


<form method="POST" name="signup" action="processform.php">

<label for="first name"></label><input id="first name" name="first_name" 
placeholder="First Name" type="text" value="<?php echo $first_name;?>" /> <span  
class="error">* <?php echo $first_nameErr;?></span>

<label for="last_name"></label><input id="last name" name="last_name"  
placeholder="Last 
Name" type="text" value="<?php echo $last_name;?>" />
<span class="error">* <?php echo $last_nameErr;?></span>
<br><br>


<label for="email"></label><input id="email" name="email" placeholder="Email"    
type="text" value="<?php echo $email;?>" />
<span class="error">* <?php echo $emailErr;?></span>
<br /><br />


<label for="password"></label><input id="password" name="password" 
placeholder="Create  
Password" type="password" />
<span class="error">* <?php echo $passwordErr;?></span>
<br /><br />
<label for="male"><strong>Male</strong></label> <input id="male" value="male" 
<?php if (isset($gender) && $gender=="male") echo "checked";?> 
name="gender" type="radio" /> 
<label for="female"><strong>Female</strong></label> <input id="female" value="female" 
<?php if (isset($gender) && $gender=="female") echo "checked";?> name="gender"  
type="radio" />
<span class="error">* <?php echo $genderErr;?></span>
<br /><br />
<label for="submit">"I Agree To <a href="#">Terms And Conditions"</a></label>  

//下面是'PROCESSFORM.PHP'

<?php

 $hostname="this is correct";
 $username="thisalso";
 $password="chicken";
 $dbname="chiken also";

  $db_conx = mysqli_connect($hostname, $username, $password) OR DIE ("Unable to
  connect to database! Please try again later.");

  if(mysqli_connect_errno())
  echo mysqli_connect_error();
  exit();
  

  $select = mysqli_select_db($db_conx,$dbname);

  $first_name= $_POST["first_name"];
  $last_name= $_POST["last_name"];
  $email= $_POST["email"];
  $password= $_POST["password"];
  $gender= $_POST["gender"];

  mysqli_query($db_conx,"INSERT INTO users (firstname, lastname, email, password,   gender)
  VALUES ('$first_name', '$last_name', '$email', '$password', '$gender')");
  mysqli_close($db_conx);

  header("Location: anotherpage.php")
  ?>

【问题讨论】:

mysql_*_escape_string 不“清理”数据(也就是说,它超出业务规则的范围!):这是一种黑客行为以防止 SQL 注入。始终将业务规则应用于数据并使用占位符来防止SQL注入。它们是两个不同的问题。见***.com/questions/60174/… 使用 mysqli 你应该使用准备好的语句 @user2864740 好的,我想我现在明白了。那么作为网页设计师,您是否必须使用黑客来防止黑客入侵? @user3066599 不。占位符不是黑客。业务规则(和其中的验证)不是黑客。占位符可防止 SQL 注入(或更改查询的 形状),而业务规则确保只允许“有效”数据。 (应适当键入数据库架构,以在适用的情况下提供故障安全规则/限制。) 如果您对此事有任何其他信息,我们会张开双臂接受,但我认为我在研究和发现的道路上是正确的。 【参考方案1】:

我们经常听到的关于 mysql*_real_escape_string() 的问题是避免 SQL 注入,因此很明显有些人开发了自己的扭曲而复杂的系统来清理任何输入并思考:“好的,现在我的输入是“安全的”,我不需要再避免 SQL 注入了。

但那是错误的,因为mysql*_real_escape_string() 和prepared statements 不是来避免SQL 注入。它们的作用是避免破坏查询(我知道,它们也用于 SQL 注入,但因为 SLQ 注入通过破坏查询并劫持它来工作,添加部件,移除其他部件等)

看看你的代码:

  $first_name= $_POST["first_name"];
  $last_name= $_POST["last_name"];
  $email= $_POST["email"];
  $password= $_POST["password"];
  $gender= $_POST["gender"];

  mysqli_query($db_conx,"INSERT INTO users (firstname, lastname, email, password,   gender)
  VALUES ('$first_name', '$last_name', '$email', '$password', '$gender')");

现在,我是一个真正天真的用户,我什至不知道注射是什么,所以我不是你不应该信任的用户。我注册到你的网站,我把我的数据放在那里:名字Ian,姓氏O'Really

什么?数据库错误?为什么?

就是这样。如果我在您的查询中加上引号,它会中断,因为引号 结束了 不应该出现的字符串,并且您的数据库收到

INSERT INTO users (firstname, lastname, email, password,   gender)
  VALUES ('Ian', 'O'Really'

这是一个 SQL 语法错误。

这就是为什么我们需要转义函数,不是因为忍者黑客总是潜伏着破坏我们的用户表并典当我们的服务器,而是因为我们不希望查询一旦被破坏语法字符被放置在错误的位置,未转义。

验证转义无关

当您希望数据采用有效格式时,您验证:日期必须格式化为日期,用户名不能包含空格,密码必须最少 8 个字符等。这些是 your 程序的 有效 输入(在我的应用中,我可能需要完全不同的规则),因此您验证它们。

转义另一方面是让控制字符在没有原意的情况下插入,使它们成为没有特殊含义的常规字符:你转义&lt;所以它不会是标签的 html 开头并且是潜在的 XSS 问题,请转义引号以避免破坏查询,等等。

不同情况不同,请记住这一点。

【讨论】:

我不敢相信我在 PHP 标记下看到了如此理智的答案。【参考方案2】:

是的,您确实需要转义字符串,因为您发送的信息将对用户可见。比如说。你有一个购物车系统。他们可以从 URL 中添加项目。因此,如果您想让它安全,请使用转义字符串。

干杯, 杰西

【讨论】:

Wha-‽ “可见性”和“来自 URL”与此有什么关系?

以上是关于验证和清理表单数据后是不是需要“my_real_escape_string”? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

清理和验证表单php

django - 如何在验证之前处理/清理字段

在 sequelize.js 中使用 build 方法时是不是需要验证、清理或转义数据

选择日期后 JS 验证报告为空

Django:清理和验证相互依赖的表格

清理和验证 PHP 表单的最常见的“最佳”方式?