// Create Your Variables
$First_Name = trim($_POST['First_Name']);
$Last_Name = trim($_POST['Last_Name']);
$Party_Size = trim($_POST['Party_Size']);
$Telephone = trim($_POST['Telephone']);
// Validate the Telephone Number before inserting into MySQL
if(!preg_match("/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/", $Telephone)) {
echo "Please go back and enter a valid Telephone number using dashes.";
// Stop the Script if the Regular Expression does not match our sequence in the Database.
exit;
}
问题如下。当我检查用户是否存在于数据库中时,脚本可以工作,但是如果添加空格,则它与数据库中的现有记录不匹配。有什么建议吗?
$check = "SELECT * FROM Weddings WHERE First_Name = '$_POST[First_Name])' AND Last_Name = '$_POST[Last_Name])'";
$results = mysqli_query($mysqli, $check);
$data = mysqli_fetch_array($results, MYSQLI_ASSOC);
if ($data > 1) {
echo "You are already in our database. Someone will contact you soon.";
exit;
}
答案 0 :(得分:1)
$firstname = mysqli_real_escape_string($mysqli, $_POST['First_Name']);
$lastname = mysqli_real_escape_string($mysqli, $_POST['Last_Name']);
$check = "SELECT * FROM Weddings WHERE First_Name LIKE '%{$firstname}%' AND Last_Name LIKE '%{$lastname}%'";
$results = mysqli_query($mysqli, $check);
$data = mysqli_fetch_array($results, MYSQLI_ASSOC);
if ($data > 1) {
echo "You are already in our database. Someone will contact you soon.";
exit;
}
如您所见,我添加了geoffrey建议的两行。
mysqli_real_escape_string - 转义字符串中的特殊字符,以便在SQL语句中使用,同时考虑连接的当前字符集。
每当您允许用户输入将在查询中使用的某些数据时,您始终应该在执行查询之前转义该数据。 并非每个用户都是友好的用户。如果用户了解SQL注入攻击,他可以轻松键入SQL的某些部分,使他能够执行您不想要的操作。< / p>
例如,假设用户输入John
作为名字,Doe
作为姓氏。与查询结合使用时,它看起来像SELECT * FROM Weddings WHERE First_Name LIKE 'John' AND Last_Name LIKE 'Doe'
。它没有错。
但是,如果用户输入1' OR '1' = '1
作为名字和姓氏,该怎么办?然后,当与查询结合使用时,它将看起来像SELECT * FROM Weddings WHERE First_Name LIKE '1' OR '1' = '1' AND Last_Name LIKE '1' OR '1' = '1'
。执行后,它将返回表中的所有行。详细了解SQL injection。
答案 1 :(得分:0)
刚刚意识到此处发布的其他答案不正确,它会执行类似查询而不是OP的意图。下面的答案会修剪发布值中的任何前导或尾随空格,为了安全性而将它们转义,然后对它们执行完全匹配。默认情况下,MySQL执行不区分大小写的搜索,因此名称的大小写无关紧要。
$firstname = mysqli_real_escape_string($mysqli, trim($_POST['First_Name']));
$lastname = mysqli_real_escape_string($mysqli, trim($_POST['Last_Name']));
$check = "SELECT * FROM Weddings WHERE First_Name = '$firstname' AND Last_Name = '$lastname'";
$results = mysqli_query($mysqli, $check);
if (mysqli_num_rows($results) > 0) {
echo "You are already in our database. Someone will contact you soon.";
exit;
}
请注意,使用某人的全名来检查是否存在是不可靠的,最好使用一些独特的内容,例如他们的电子邮件地址。
答案 2 :(得分:0)
脚本有两个问题。发布的数据会受到污染,直到您检查到您是否从用户那里得到了您的期望。此时,用户可以输入名字“123”。因此,应该检查是否按字母顺序排列,并且应检查姓氏的字母顺序以及撇号或连字符的可能性,因此接受姓名如“O'Reilly”以及“Smith-Jones”的姓氏,如如下:
<?php
$fname = $lname = "";
// check for tainted data
if (ctype_alpha($_POST['First_Name'])) {
$fname = trim($_POST['First_Name']);
}
if ( preg_match("/^[a-zA-Z'-]+$/, $_POST['Last_Name']) ) {
$lname = trim($_POST['Last_Name']);
}
一旦数据验证,则将数据传递给trim()以删除多余的空格字符(例如空格,制表符,换行符等)是合适的。
第二个问题是确保查询不易受SQL注入攻击。
<?php
if (strlen($fname) > 0 && strlen($lname) > 0) {
$firstname = mysqli_real_escape_string($link, trim($fname));
$lastname = mysqli_real_escape_string($link, trim($fname));
$query = "SELECT * FROM Weddings WHERE First_Name = '$firstname' AND Last_Name = '$lastname'";
$results = mysqli_query($link, $query or die( mysqli_error($link) ) );
if (mysqli_num_rows( $results ) > 0) {
echo "You are already in our database. Someone will contact you soon.";
exit;
}
mysqli_close($link);
}
如果你是黑客,你仍然可以解决mysqli_real_escape_string()这个问题没有得到充分解决。根据{{3}}:
字符集必须在服务器级别设置,或者使用 API函数mysqli_set_charset()让它影响 mysqli_real_escape_string()。
此Manual提供了进一步的见解。因此,实际上最好使用article,如下所示:
<?php
$dbh = new PDO("mysql:host=localhost;dbname=database", 'username', 'password');
$stmt = $dbh->prepare("SELECT * FROM Weddings WHERE First_Name = ? AND Last_Name = ?");
if ($stmt->execute( array( $fname,$lname))) {
$row = $stmt->fetch(PDO::FETCH_ASSOC));
if ($row !== FALSE){
echo "You are already in our database. Someone will contact you soon.";
}
}