PHP表单垃圾邮件防护

4
请谅解,我是一名具有一定编程知识的平面设计师,但并不像开发者那样专业。经过许多小时的摸索和向Google提问后,我决定直接向大家寻求帮助!
我一直在构建网站联系表单。目前为止还不错,只有一个问题。我想添加一个简单的防垃圾邮件字段。
我已经添加了一个名为“spamcheck”的字段,问题是6+2=? 但我不知道如何编写PHP代码要求该值必须是8。只要其他字段正确填写,提交表单时,无论输入什么数字,表单都会被提交,这就是为什么您会看到我的$ spamcheck变量,但当前编码仅要求它具有与其他字段相同的值。
我已经包含了PHP,PHP调用的验证和表单。如果表单有一些多余的代码,请原谅;我尝试了许多不同版本的PHP表单教程,但没有成功。
当然,非常感谢您的帮助!:)
以下是我直接放置在网页中的PHP代码:
<?php 
define("EMAIL", "email@gmail.com");

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

  include('validate.class.php');

  //assign post data to variables 
    $name = trim($_POST['name']);
    $email = trim($_POST['email']);
    $budget = trim($_POST['budget']);
    $deadline = trim($_POST['deadline']);
    $message = trim($_POST['message']);
    $spamcheck = trim($_POST['spamcheck']);

  //start validating our form
  $v = new validate();
  $v->validateStr($name, "name", 1, 50);
  $v->validateEmail($email, "email");
  $v->validateStr($budget, "budget");
  $v->validateStr($deadline, "deadline");
  $v->validateStr($message, "message", 1, 1000);
  $v->validateStr($spamcheck, "spamcheck");

  if(!$v->hasErrors()) {
       $from = "website.com"; //Site name
  // Change this to your email address you want to form sent to
  $to = "email@gmail.com"; 
  $subject = "Hello! Comment from " . $name . "";

  $message = "Message from " . $name . "
  Email: " . $email . " 
  Budget: " . $budget ."
  Deadline: " . $deadline ."
  Message: " . $message ."";
  mail($to,$subject,$message,$from);


    //grab the current url, append ?sent=yes to it and then redirect to that url
        $url = "http". ((!empty($_SERVER['HTTPS'])) ? "s" : "") . "://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
        header('Location: '.$url."?sent=yes");

    } else {
    //set the number of errors message
    $message_text = $v->errorNumMessage();       

    //store the errors list in a variable
    $errors = $v->displayErrors();

    //get the individual error messages
    $nameErr = $v->getError("name");
    $emailErr = $v->getError("email");
    $budgetErr = $v->getError("budget");
    $deadlineErr = $v->getError("deadline");
    $messageErr = $v->getError("message");
    $spamcheckErr = $v->getError("spamcheck");

  }//end error check
}// end isset
  ?>

这是validate.class.php文件,它被调用来:
<?php
class validate {

  public $errors = array();

   public function validateStr($postVal, $postName, $min = 1, $max = 1000) {
    if(strlen($postVal) < intval($min)) {
      $this->setError($postName, ucfirst($postName)." is required.");
    } else if(strlen($postVal) > intval($max)) {
      $this->setError($postName, ucfirst($postName)." must be less than {$max} characters long.");
    }
  }// end validateStr

   public function validateEmail($emailVal, $emailName) {
    if(strlen($emailVal) <= 0) {
      $this->setError($emailName, "Please enter an Email Address");
    } else if (!preg_match('/^[^0-9][a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)*[@][a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)*[.][a-zA-Z]{2,4}$/', $emailVal)) {
      $this->setError($emailName, "Please enter a Valid Email Address");
        }
  }// end validateEmail     

  private function setError($element, $message) {
    $this->errors[$element] = $message;
  }// end logError


  public function getError($elementName) {
    if($this->errors[$elementName]) {
      return $this->errors[$elementName];
    } else {
      return false;
    }
  }// end getError

  public function displayErrors() {
    $errorsList = "<ul class=\"errors\">\n";
    foreach($this->errors as $value) {
      $errorsList .= "<li>". $value . "</li>\n";
    }
    $errorsList .= "</ul>\n";
    return $errorsList;
  }// end displayErrors

  public function hasErrors() {
    if(count($this->errors) > 0) {
      return true;
    } else {
      return false;
    }
  }// end hasErrors

  public function errorNumMessage() {
    if(count($this->errors) > 1) {
            $message = "There was an error sending your message!\n";
        } else {
            $message = "There was an error sending your message!\n";
        }
    return $message;
  }// end hasErrors

}// end class
?>

以下是HTML/PHP表单代码:

<span class="message"><?php echo $message_text; ?></span>
   <?php if(isset($_GET['sent'])): ?><h2>Your message has been sent</h2><?php endif; ?>
          <form role="form" method="post" action="webpage.php#contact">
            <div class="form-group">
              <input type="text" name="name" class="form-control" id="name" value="<?php echo htmlentities($name); ?>" placeholder="Full Name" required>
              <label for="exampleInputName"><i class="icon-tag"></i></label>
              <span class="errors"><?php echo $nameErr; ?></span>
              <div class="clearfix"></div>
            </div>
            <div class="form-group">
              <input type="email" name="email" class="form-control" id="email" value="<?php echo htmlentities($email); ?>" placeholder="Email" required>
              <label for="exampleInputEmail1"><i class="icon-inbox"></i></label>
              <span class="errors"><?php echo $emailErr; ?></span>
              <div class="clearfix"></div>
            </div>
            <div class="form-group">
              <input type="text" name="budget" class="form-control" id="budget" value="<?php echo htmlentities($budget); ?>" placeholder="Budget" required>
              <label for="exampleInputBudget1"><i class="icon-usd"></i></label>
              <span class="errors"><?php echo $budgetErr; ?></span>
              <div class="clearfix"></div>
            </div>
            <div class="form-group">
              <input type="text" name="deadline" class="form-control" id="deadline" value="<?php echo htmlentities($deadline); ?>" placeholder="Deadline" required>
              <label for="exampleInputDeadline"><i class="icon-calendar"></i></label>
              <span class="errors"><?php echo $deadlineErr; ?></span>
              <div class="clearfix"></div>
            </div>
            <div class="form-group textarea">
              <textarea rows="6" name="message" class="form-control" id="message" value="<?php echo htmlentities($message); ?>" placeholder="Write Message" required></textarea>
              <label for="exampleInputMessage"><i class="icon-pencil"></i></label>
              <span class="errors"><?php echo $messageErr; ?></span>
              <div class="clearfix"></div>
            </div>
            <div class="form-group">
              <input type="text" name="spamcheck" class="form-control" id="spamcheck" value="<?php echo htmlentities($spamcheck); ?>" placeholder="Spam check: 6+2=?" required>
              <label for="exampleInputSpamCheck"><i class="icon-lock"></i></label>
              <span class="errors"><?php echo $spamcheckErr; ?></span>
              <div class="clearfix"></div>
            </div>

            <button type="submit" id="submit" name="submit" value="submit" class="btn btn-large">Send Message</button>
          </form>
3个回答

3
在生成表单的PHP脚本中,您应该将问题的正确答案保存在 $_SESSION 变量 中。
然后,在接收此表单数据的PHP脚本中,您应该验证提交的问题是否与 $_SESSION 变量中的正确答案匹配。
有许多关于如何在PHP中使用会话的教程
基本上,它归结为:
<?php
    session_start();
    $_SESSION['captcha_right_answer'] = somehow_generate_this();
?>

handler.php

<?php
    session_start();

    if ($_INPUT['captcha_answer'] != $_SESSION['captcha_right_answer']) {
        // Show "bad captcha" message, re-show form, whatever
    }
    else {
        // Captcha good - go on with life
    }
?>

谢谢您的快速回复!我必须承认我不确定如何编写这个。我理解足够的PHP来编辑变量名/错误消息。但不足以编写像这样的东西。您介意向我展示如何吗? - kgthree

1

尝试使用this作为验证码的替代方案。然后,您可以使用现有的类来验证字段。假设您的隐藏字段名称为“fakeField”,您可以通过validateSTR方法对其进行验证。

$v->validateStr($fakeField, "fakeField",0,0);

由于您的字符串检查正在检查>和<而不是>=和<=,因此长度恰好为0时将返回true。对于那些没有太多代码知识的人来说,这可能是一个更容易的解决方案。

或者,如果您坚持使用某种验证码,并且知道您期望的值,可以添加一个方法来检查该值。

该方法:

public function validateCaptcha( $value,$name, $expectedValue) {
if(trim($value) != $expectedValue) {
  $this->setError($name, "Captcha Incorrect");
    }
}

然后更改代码行

$v->validateStr($spamcheck, "spamcheck");

$v->validateCaptcha($spamcheck, "spamcheck", '6');

这不是最好的解决方案,因为有很多强大的验证码可用,但它很容易使用。


非常感谢!这对我来说肯定比 $_SESSION 少了很多麻烦,我能够让你们两个的示例都正常工作。我知道有更好的验证码,但这不是一个高流量的网站,应该足以筛选出机器人。 - kgthree

0
另一种简单的方法是捕获页面加载的时间并将其与表单提交的时间进行比较。如果差异太小,则退出页面。垃圾邮件机器人很快,而人类则很慢。垃圾邮件机器人可能会找出各种字段 - 甚至进行数学计算 - 但它们永远不会等待超过几秒钟。
在表单中只需要两行代码即可:
<input name="timeloaded" type="hidden" value="<?php echo time();?>" />

还有一个表单处理代码:

if(!(is_numeric($_POST['timeloaded'])) || time()-$_POST['timeloaded']<30) {header("Location: index.php"); exit;} 

这个是针对一个无法在30秒内由人类填写完的表单。根据您使用的表单长度进行更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接