【问题标题】:PHP exception handling after SQL insert [duplicate]SQL插入后的PHP异常处理[重复]
【发布时间】:2016-11-06 09:27:17
【问题描述】:

我正在用 php 创建一个非常简单的注册表单,目前当用户尝试注册时,会弹出一个带有成功或失败消息的 javascript 警报。

现在我想捕获 sql 异常以显示数据库中是否已经存在用户名或电子邮件,而不是标准的失败消息。

这是我目前的代码:

if(isset($_POST['btn-signup']))
{
  $uname = mysql_real_escape_string($_POST['uname']);
  $email = mysql_real_escape_string($_POST['email']);
  $upass = md5(mysql_real_escape_string($_POST['pass']));

  if(mysql_query("INSERT INTO user(username,password,email) VALUES('$uname','$upass','$email')"))
{
?>
    <script>alert('successfully registered ');</script>
<?php
}
else{
?>
    <script>alert('error while registering you...');</script>
<?php
 }
}
?>

如何检查电子邮件或用户名是否已存在于数据库中?这两个变量在数据库中已经是唯一的。

【问题讨论】:

标签: php mysql


【解决方案1】:
$con=mysqli_connect("localhost","root","","my_db");
$check="SELECT COUNT(*) FROM persons WHERE Email = '$_POST[eMailTxt]'";
if (mysqli_query($con,$check)>=1)
{
    echo "User Already in Exists<br/>";
}
else
{
    $newUser="INSERT INTO persons(Email,FirstName,LastName,PassWord) values('$_POST[eMailTxt]','$_POST[NameTxt]','$_POST[LnameTxt]','$_POST[passWordTxt]')";
    if (mysqli_query($con,$newUser))
    {
        echo "You are now registered<br/>";
    }
    else
    {
        echo "Error adding user in database<br/>";
    }
}

【讨论】:

  • 不鼓励仅使用代码的答案。解释你的答案。
  • 另外,恭喜。 您的答案提供了执行 SQL 注入的能力。使用mysqli 本身并不安全。 绑定你的参数.
  • 正如您所说,检查一百万用户的用户名将是一项繁重的工作,因此您可以检查结果计数。计数同时做两项工作,一项用于搜索,另一项用于 mysqli_num_rows 一项。
  • 好吧,我的朋友,这只是为了理解 sql 注入和其他东西是在内置函数或我们创建的函数的帮助下处理的。
  • @SarthakPandit 教一个人如何自己做事,比教他依赖什么要好。
【解决方案2】:

来自评论:

我不想要 2 个查询,而数据库可以为我返回异常。如果该表中有大约 1000 万条记录,我不想在插入新记录之前检查它们。

好的,所以您要插入一个查询并检查是否唯一?所以你必须在UNIQUE_INDEX MySQL 列上插入,你可以用下面的答案shameless stolen from this answerthis question 来捕捉这些异常:

在这个答案的情况下,我们假设您正在使用 PDO,因为您应该这样做。请阅读它。

// Pre-setup the database connection somewhere, usually an include (or a class)
$link = new PDO("mysql:host=$dbhost;dbname=$dbname",$dbusername,$dbpassword);
// PDO needs to be set in Exception mode:
$link->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

//Input Processing functions.
// (entirely optional)
$uname = MyCleanerFunction($_POST['uname']);
$email = MyCleanerFunction($_POST['email']);
//please see note below re:MD5
//$upass = md5($_POST['pass']); 
$options['cost'] = 12;
$upass = password_hash($_POST['pass'],PASSWORD_BCRYPT,$options);

//now reach the code part:
    try {
        //PDO query execution goes here:

         $statement = $link->prepare("INSERT INTO user(username,password,email) VALUES(:uname, :email, :pass)"));
         $statement->bindValue(":uname", $uname);
         $statement->bindValue(":email", $email);
         $statement->bindValue(":pass", $upass);
         $statement->execute();
         //reaching here everything is ok! 
    }
    catch (\PDOException $e) {
        if ($e->errorInfo[1] == 1062) {
            // The INSERT query failed due to a key constraint violation.
            // THIS means that it failed because the Primary Key 
            // (the email) appears already in the database table.
        }
        if($e->errorInfo[1] == 9999){
          // possible other IF clauses for other errors in INSERT.
        }
    }

您也可以好好阅读一下catching and outputting PDO errors。以及关于MySQL Unique Key Constraints 的所有内容。

  • Should not catch PDO exceptions也是非常有用的另类观点。

  • 另外请注意,MD5 是一个非常弱 用于存储密码的哈希,PHP password_hash 函数是首选的方法。

  • 为您的 MySQL 交互使用准备好的语句,上面的布局是它们外观的粗略指南,并且与 MySQLiPDO 非常相似。 Prepared Statements 在保护您的数据免受恶意用户输入方面大有帮助。

【讨论】:

  • 您能否在答案中的密码上使用md5() 做个说明。
  • MyCleanerFunction 如果使用绑定参数,则不需要存在。
  • 从技术上讲,不,但我个人总是希望在获得数据后立即对数据进行某种边缘情况清理。我也希望在那里有占位符函数可以帮助 OP 在写 PDO 语句之前意识到过滤和清理可以很舒服地进行。
  • 鉴于问题中的代码,它看起来像是建议继续使用mysql_real_escape_string - 小心在答案中粘贴未提及的代码,希望 OP/阅读器能读懂您想要的含义。
  • @AD7six 我不认为它看起来像那样,但我已经更新了答案。这不是“无意”的代码,代码来自 OP 的原始代码,因此最坏的情况是它们可以作为查看新布局/结构的参考。
猜你喜欢
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 2018-08-14
  • 2022-06-15
  • 1970-01-01
  • 1970-01-01
  • 2012-11-27
  • 2014-01-06
相关资源
最近更新 更多