首页 > 解决方案 > 使用 PHP 对联系表单 POST 进行服务器端验证,当它应该为真时,秘密返回假

问题描述

所以基本上我有一个使用 mail() 函数发送的联系表,我实现了几个验证,如 reCaptcha 和模式、蜜罐等,它工作得很好,但并不完美,而且客户很挑剔,想要更少的垃圾邮件。现在我正在尝试使用秘密哈希添加服务器端验证,如此处所示https://css-tricks.com/serious-form-security/

我想坚持这样一个事实,即在没有verifyFormToken('form1')附加条件的情况下一切都可以完美运行。我已经检查过,当我删除第一个条件和最后一个条件时,该函数返回 true,因此它与服务器上的令牌有关。我试图摆脱我认为是完全绕过我的表单/JS并直接发布的最后几封垃圾邮件。我还检查了一些现有问题,包括这个PHP 表单关键错误


require_once './php/recaptcha/src/autoload.php';
$siteKey = 'xxxxx';
$secret = 'xxxxxxxxx';
$name = $_POST['name'];
$email = $_POST['email'];
$telephone = $_POST['telephone'];
$company = $_POST['company'];
$message = $_POST['message'];
$recipient = "sales@xxxx.com";
$formcontent=" From: $name \n Phone: $telephone \n Company: $company \n Message: $message";
$subject = "Contact Form - QUOTE APPLICATION - EN";
$mailheader = "From: $email \r\n";
$recaptcha = new \ReCaptcha\ReCaptcha($secret);
$gRecaptchaResponse = $_POST['g-recaptcha-response']; //google captcha post data
$remoteIp = $_SERVER['REMOTE_ADDR']; //to get user's ip
$resp = $recaptcha->verify($gRecaptchaResponse, $remoteIp); //method to verify captcha

session_start();

function generateFormToken($form) {
  $_SESSION[$form.'_token'] = md5(uniqid(microtime(), true));
  return $_SESSION[$form.'_token'] ;
}

function verifyFormToken($form) {
  if (!isset($_SESSION[$form.'_token'])) { return false;}
  if (!isset($_POST['token'])) {return false;}
  if ($_SESSION[$form.'_token'] !== $_POST['token']) {return false;}
  return true;
}


if(isset($_POST['submit_client'])) {
    $newToken = generateFormToken('form1'); 
    $recaptcha = new \ReCaptcha\ReCaptcha($secret);
    $gRecaptchaResponse = $_POST['g-recaptcha-response']; //google captcha post data
    $remoteIp = $_SERVER['REMOTE_ADDR']; //to get user's ip
    $resp = $recaptcha->verify($gRecaptchaResponse, $remoteIp); //method to verify captcha
    
            if (($resp->isSuccess()) && (!empty($name)) && (preg_match("/^[a-zA-Z ]*$/", $name))  && (!empty($telephone)) && (preg_match("/^[0-9-+\s()]*$/", $telephone)) && (!empty($email)) && (preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $email))) {
                        
                        if (verifyFormToken('form1')) {
                        mail($recipient, $subject, $formcontent, $mailheader) or die("Error!");
                        echo '<script language="javascript">alert("Thank you, we\'ll be in touch shortly!");</script>';
                        }}
            else {
                die("Error!");
            }
}


     <form style="position:relative;" class="contact-us-form contact-us-form2" method="POST">
        <h2 class="">quote request</h2>
        <div style="display:flex;justify-content:center;">
        <fieldset>
          <input name="name" placeholder="Name*" type="text" tabindex="1" required pattern="[a-zA-Z ]*$" autofocus>
        </fieldset>
        <fieldset>
          <input name="email" placeholder="Email*" type="text" pattern="[A-Za-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$" tabindex="2" required>
        </fieldset>
        </div>
        <div style="display:flex;justify-content:center;">
        <fieldset>
          <input name="telephone" placeholder="Telephone*" type="text" pattern="[0-9-+\s()]*$" tabindex="3" required>
        </fieldset>
        <fieldset>
          <input name="company" placeholder="Company" type="text" tabindex="4">
          <input name="token" type="hidden" value="<?php echo $newToken; ?>">
        </fieldset>
        </div>
        <div style="display:flex;justify-content:center;">
        <fieldset>
          <textarea name="message" placeholder="Tell us more about your request*" rows="8" cols="30" tabindex="5" required></textarea>
        </fieldset>
        </div>
         <div id="send-captcha-container">
          <input name="token" type="hidden" value="<?=$newToken;?>">
          <input id="submit-client-button" class="cta contact-form-submit-btn" style="cursor:pointer;border:none!important;" type="submit" name="submit_client" value="send" disabled>
          <div class="g-recaptcha" data-callback="recaptcha_callback" data-expired-callback="recaptcha_expired_callback" data-sitekey="6Ldcw70ZAAAAAMkOcdoWhQPn8ey2opCbwRIZJe5M"></div>
         </div>
        </form>

标签: phphtmlvalidationmd5contact-form-7

解决方案


那里有2个错误:

  1. 第一个错误是您需要一个发送 POST 变量“submit_client”的提交按钮,因为您正在检查它。
  2. 第二个错误是您必须在验证后制作令牌,因此在发送每个 POST 之前不会对其进行修改


require_once './php/recaptcha/src/autoload.php';
$siteKey = 'xxxxx';
$secret = 'xxxxxxxxx';
$name = $_POST['name'];
$email = $_POST['email'];
$telephone = $_POST['telephone'];
$company = $_POST['company'];
$message = $_POST['message'];
$recipient = "sales@oxoinnovation.com";
$formcontent=" From: $name \n Phone: $telephone \n Company: $company \n Message: $message";
$subject = "Contact Form - QUOTE APPLICATION - EN";
$mailheader = "From: $email \r\n";
$recaptcha = new \ReCaptcha\ReCaptcha($secret);
$gRecaptchaResponse = $_POST['g-recaptcha-response']; //google captcha post data
$remoteIp = $_SERVER['REMOTE_ADDR']; //to get user's ip
$resp = $recaptcha->verify($gRecaptchaResponse, $remoteIp); //method to verify captcha

session_start();

function generateFormToken($form) {
  $_SESSION[$form.'_token'] = md5(uniqid(microtime(), true));
  return $_SESSION[$form.'_token'] ;
}

function verifyFormToken($form) {
  if (!isset($_SESSION[$form.'_token'])) { return false;}
  if (!isset($_POST['token'])) {return false;}
  if ($_SESSION[$form.'_token'] !== $_POST['token']) {return false;}
  return true;
}


if(isset($_POST['submit_client'])) {

    /*
       Take this out here
    */  
    // $newToken = generateFormToken('form1'); 


    $recaptcha = new \ReCaptcha\ReCaptcha($secret);
    $gRecaptchaResponse = $_POST['g-recaptcha-response']; //google captcha post data
    $remoteIp = $_SERVER['REMOTE_ADDR']; //to get user's ip
    $resp = $recaptcha->verify($gRecaptchaResponse, $remoteIp); //method to verify captcha
    
            if (($resp->isSuccess()) && (!empty($name)) && (preg_match("/^[a-zA-Z ]*$/", $name))  && (!empty($telephone)) && (preg_match("/^[0-9-+\s()]*$/", $telephone)) && (!empty($email)) && (preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $email))) {
                        
                        if (verifyFormToken('form1')) {
                        mail($recipient, $subject, $formcontent, $mailheader) or die("Error!");
                        echo '<script language="javascript">alert("Thank you, we\'ll be in touch shortly!");</script>';
                        }}
            else {
                die("Error!");
            }
}


/*
     and put it here 
*/ 
$newToken = generateFormToken('form1');




推荐阅读