PHP订单确认系统验证码验证失败问题求助
我正在开发一款基于PHP的订单确认系统,当前遭遇验证码验证异常问题:验证码可成功生成并通过邮件发送给用户,但用户输入验证码进行验证时,系统无法识别其为正确代码。
相关代码
<?php session_start(); if (!isset($_SESSION['user'])) { header('location:../connexion.php'); } else { require_once '../connectDB.php'; if (isset($_GET['id'])) { $commandeId = $_GET['id']; $commande = $database->prepare("SELECT produits.idProduit, produits.nomProduit, produits.imageType, produits.image, commandeDetails.Quantite, produits.prixProduit FROM commandeDetails INNER JOIN produits ON commandeDetails.IDProduit = produits.idProduit WHERE IDCommande = :orderID"); $commande->bindParam(":orderID", $commandeId); $commande->execute(); if ($commande->rowCount() > 0) { $emailUser = $_SESSION['user']->email; require_once '../mail.php'; // $verificationCode = 'ddec5800'; $verificationCode = substr(md5(uniqid(mt_rand(), true)), 0, 8); $cmd = $database->prepare("UPDATE commandes SET verificationCode = :verificationCode WHERE idCommande = :commandeId"); $cmd->bindParam(":verificationCode", $verificationCode); $cmd->bindParam(":commandeId", $commandeId); // $_SESSION['verification_code'] = $verificationCode; $cmd->execute(); $verifCodeQuery = $database->prepare("SELECT verificationCode FROM commandes WHERE idCommande = :commandeId"); $verifCodeQuery->bindParam(":commandeId", $commandeId); $verifCodeQuery->execute(); $verificationCode = $verifCodeQuery->fetch(PDO::FETCH_COLUMN); $mail->addAddress($emailUser); $mail->Subject = "Confirmation de Commande - DRCoffee"; $mail->Body = ' <h1>DRCoffee</h1> <h2>Confirmation de Commande</h2> <p>Merci de votre commande sur DRCoffee. Utilisez le code de vérification ci-dessous pour confirmer votre commande :</p> <h3>Code de Vérification: ' . $verificationCode . '</h3> <p>Entrez ce code lors du processus de confirmation de commande.</p> <p>Merci de choisir DRCoffee!</p> <p>L\'équipe DRCoffee</p> <p>DRCoffee - Casablanca, Maroc</p> '; $mail->setFrom("oyuncoyt@gmail.com", "DRCoffee"); $mail->send(); } if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['verification'])) { $verife = $database->prepare('SELECT verificationCode FROM commandes WHERE idCommande = :commandeId'); $verife->bindParam(":commandeId", $commandeId); $verife->execute(); $code = $verife->fetch(PDO::FETCH_COLUMN); if ($_POST['verification_code'] == $code) { $updateStock = $database->prepare("UPDATE produits SET stock = stock - :quantitySold WHERE idProduit = :productId"); while ($commandeDetails = $commande->fetch(PDO::FETCH_ASSOC)) { $productId = $commandeDetails['idProduit']; $quantitySold = $commandeDetails['Quantite']; $updateStock->bindParam(":quantitySold", $quantitySold); $updateStock->bindParam(":productId", $productId); $updateStock->execute(); } $commande->execute(); $updateStatus = $database->prepare("UPDATE commandes SET etat = 'Confirmée' WHERE idCommande = :orderId"); $updateStatus->bindParam(":orderId", $commandeId); $updateStatus->execute(); header('Location: confirmation-success.php'); exit(); } else { header('Location: about.php'); exit(); } } } ?>
已尝试的排查步骤
- 确认验证码已成功生成并存储至数据库;
- 验证邮件已正确发送给用户且包含正确验证码;
- 确认用户在验证过程中输入的代码无误;
- 检查数据库,确认验证码可被正确调取用于比对;
- 检查验证流程执行过程中是否存在错误信息或异常。
当前疑问
- 我的验证码逻辑是否存在潜在漏洞?
- 邮件内容发送是否正确,是否会影响验证流程?
- 有哪些调试建议可用于定位验证流程的失败环节?
期望结果
用户输入的验证码可与数据库中存储的代码匹配,完成订单确认,但目前输入正确代码仍无法通过验证,恳请提供解决思路与建议。
一、验证码逻辑的潜在漏洞排查
POST请求结果集指针耗尽问题
页面加载时已执行$commande->execute()并读取过订单详情,POST验证通过后再次调用while ($commandeDetails = $commande->fetch(...))时,PDO结果集指针已处于末尾,无法获取数据。虽然不直接影响验证码验证,但会导致库存更新失败,甚至引发后续异常。建议在POST分支重新执行订单查询,或提前将结果存入数组:// POST分支内重新查询订单详情 $commande = $database->prepare("SELECT produits.idProduit, commandeDetails.Quantite FROM commandeDetails INNER JOIN produits ON commandeDetails.IDProduit = produits.idProduit WHERE IDCommande = :orderID"); $commande->bindParam(":orderID", $commandeId); $commande->execute();松散比对的风险
当前使用==松散比对,若数据库中验证码为字符串、用户输入被解析为其他类型(如数字),可能出现匹配异常。改用===进行严格类型+值比对:if ($_POST['verification_code'] === $code) { // 验证通过逻辑 }页面刷新导致验证码覆盖
每次GET请求都会重新生成并更新数据库验证码,若用户多次刷新页面,数据库中验证码会被覆盖,用户收到的旧邮件验证码自然无法匹配。添加判断,仅当订单无验证码时才生成发送:$checkCode = $database->prepare("SELECT verificationCode FROM commandes WHERE idCommande = :commandeId"); $checkCode->bindParam(":commandeId", $commandeId); $checkCode->execute(); $existingCode = $checkCode->fetch(PDO::FETCH_COLUMN); if (empty($existingCode)) { // 生成并发送验证码的逻辑 }
二、邮件内容对验证流程的影响
从代码看,邮件验证码直接取自数据库,不会直接导致验证失败,但需注意两点:
- 检查HTML渲染是否产生不可见字符:比如
<h3>标签的样式是否导致验证码前后出现空格,可在邮件中添加纯文本版本的验证码,或提示用户复制纯文本内容。 - 确认邮件发送时未对验证码进行转义/编码,避免实际发送内容与数据库存储不一致。
三、调试建议
输出比对的具体值
在POST验证分支临时添加代码,直观查看用户输入与数据库取出的验证码细节:// POST分支内 var_dump($_POST['verification_code'], $code); exit;可排查空格、大小写、字符编码等差异。
开启PHP错误提示
在代码开头添加,捕获未处理的PDO错误或变量异常:error_reporting(E_ALL); ini_set('display_errors', 1);核对表单参数名
确认前端输入框的name属性为verification_code,与后端$_POST['verification_code']完全一致,避免拼写错误。验证订单ID的有效性
确认POST请求时$commandeId正确,比如表单中通过隐藏域传递订单ID,避免因ID错误查询到无关验证码。
内容的提问来源于stack exchange,提问作者Noureddine DRIOUECH

