0

I want to put a honeypot on my website to stop spambots from filing out my form.

I found this answer which seems useful. It advises to include an invisible checkbox on your page:

<input
  type="checkbox"
  name="contact_me_by_fax_only"
  value="1"
  style="display:none !important"
  tabindex="-1"
  autocomplete="off"
>

But then, PHP is suggested to test whether the checkbox has been checked:

$honeypot = FALSE;
if (!empty($_REQUEST['contact_me_by_fax_only']) && (bool) 
$_REQUEST['contact_me_by_fax_only'] == TRUE) {
    $honeypot = TRUE;
    log_spambot($_REQUEST);
    # treat as spambot
} else {
    # process as normal
}

I've not used much PHP before. My questions:

  1. Can I just put this PHP in my html code with surrounding <?php ?> tags?
  2. If so, does it matter where I put the PHP? Does it have to be after the form (for example)?
  3. In the part of the PHP that says #process as normal, do I need to put anything in here?
  4. Or am I supposed to put the PHP in my post.php file which I created to post my form?

If it helps, the form part of my html code:

<form action="post.php" method="post">
   </br>
   <label for="email"></label>
   <input type="email" placeholder="Enter your email address..."
             name="email" required>
    <button type="submit" class="signupbtn">Sign Up</button>
    <input type="checkbox" name="contact_me_by_fax_only"
      value="1" style="display:none !important" tabindex="-1" autocomplete="off">
</form>

I'm trying to follow the answer on this. I'm still not sure where everything should go. I don't understand when I am telling the code to do when it's a human response; I want it to submit the form, but I don't know how it fits together with the php.

<html>

  <head>

    <title>Page Title</title>
    <link href="https://fonts.googleapis.com/css?family=Quicksand"
          rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="style.css">
    <link rel="shortcut icon" href="fav.ico" >
    <meta name="description" content="">
  </head>

  <body>

    <div class="home_pic">
      <img border="0" style="border-color: black" src="pic1.png"
           height="700px">
    </div>
    <div class="home_text">
        Some words for the website
    </div>

    <?php
    if (isset($_REQUEST['contact_me_by_fax_only']) && (bool)
    $_REQUEST['contact_me_by_fax_only'] == TRUE) {
       $honeypot = TRUE;
       log_spambot($_REQUEST);
       // treat as spambot  -- I don't need it to *do* anything if spambot
    ?>

    <?php
        exit();  // all done if a spambot
    } else {
        // process as normal -- here we will use a function, note that in PHP
        // scope rules will hide most global variables from the function!
        process_human_response();
    }
    function process_human_response()
    {

    <!--DOES THE FORM GO IN HERE NOW?-->

    <form action="post.php" method="post">
          </br>SIGN UP:
          <label for="email"></label>
          <input type="email" placeholder="Enter your email address..."
                 name="email" required>
          <button type="submit" class="signupbtn">Sign Up</button>
          <input type="checkbox" name="contact_me_by_fax_only"
          value="1" style="display:none !important" tabindex="-1" autocomplete="off">
    </form>

    ?>

  </body>

</html>

Sorry, I'm very confused.

user1551817
  • 6,693
  • 22
  • 72
  • 109
  • 1
    PHP code can be anywhere on the page but note *it runs on the server before the code is sent to the browser*. If your PHP code is `echo "hello!";` then only the text `Hello!" is added to the page response at that point, the client / browser never sees or runs any PHP code. To do things client-side you need JavaScript, but spammers will not be running your page at all so it's useless against them. – Dave S Oct 04 '19 at 21:36
  • 2
    Checkboxes require `isset()`, not `empty()` in order to work properly. – Funk Forty Niner Oct 04 '19 at 22:08
  • You have *2* pages / files: form entry page that does not have spambot detection, form processing page (my answer) that detects spambot and either processes the form data or just throws it away. On your form entry page you can also add ReCAPTCHA to make robots suffer - https://www.google.com/recaptcha/intro/v3.html – Dave S Oct 08 '19 at 16:47
  • For processing the human form data, that usually means either sending an email to someone or adding to a database using PDO commands. – Dave S Oct 08 '19 at 16:50
  • I do not recommend ReCAPTCHA unless you are comfortable inconveniencing (sometimes severely) legitimate users. When using random sites, I can't count how many times it's made me click through 3 or more images giving me progressively more challenging tasks before accepting that I'm not a bot. Sometimes I get pissed and give up. Your users will do this. For this reason I prefer other methods to catch or exclude spambots. – cazort Nov 06 '21 at 13:46

1 Answers1

1

In the accepted answer to Better Honeypot Implementation (Form Anti-Spam)

That is the PHP for the processing page that your form submits to.

Copying code from Nicholas Summers' post, I'll add some sample HTML to clarify it.

<?php
$honeypot = FALSE;
if (!empty($_REQUEST['contact_me_by_fax_only']) && (bool) 
$_REQUEST['contact_me_by_fax_only'] == TRUE) {
    $honeypot = TRUE;
    log_spambot($_REQUEST);
    // treat as spambot  -- here we will place the HTML "inline"
?>
<html>
<body>
<p>Tasty spam, thanks!</p>
</body>
</html>
<?php
    exit();  // all done if a spambot
} else {
    // process as normal -- here we will use a function, note that in PHP
    // scope rules will hide most global variables from the function!
    process_human_response();
}

function process_human_response()
{
   //... get data from $_REQUEST
   //... process data
?>
<html>
<body>
<p>Thank you good human!</p>
</body>
</html> 

This shows placing your code and HTML "inline" at the global level for the first case (spam) and in a function for humans just to show another way.


As pointed out, the code is often shorter and easier to maintain if you don't duplicate any of the shared HTML, like this:

Shared beginning of page:

<html>
<head> <!-- and shared CSS, JS files here --> </head>
<body>

Some PHP logic to decide if it is a spambot

<?php
if (isset($_REQUEST['contact_me_by_fax_only']) && (bool) 
$_REQUEST['contact_me_by_fax_only'] == TRUE) {
    $honeypot = TRUE;
    log_spambot($_REQUEST);
    // treat as spambot  -- here we will place the HTML "inline"
?>

Include the response HTML for a spambot, done "inline". Because this is in the "if" case of the PHP code this HTML will only be sent to the browser when the if test is true (= spambot)

<p>Tasty spam, thanks!</p>

Continue the PHP code for the if case, then switch to the else case.

<?php
    exit();  // all done if a spambot
} else {
    // process as normal -- here we will use a function, note that in PHP
    // scope rules will hide most global variables from the function!
    process_human_response();
}
?>

Shared HTML for end of page

</body>
</html>

The function called about to process a human response

function process_human_response()
{
   //... get data from $_REQUEST
   //... process data
?>

This HTML is inside of the function, so it is only sent if this function is called

<p>Thank you good human!</p>

finish the function

<?php
}
?>
Dave S
  • 1,427
  • 1
  • 16
  • 18
  • 1
    @FunkFortyNiner - I agree, but I think the example is clearer for someone new to PHP if I don't add that optimization. Spam response vs. Human Response instead of Shared Page Beginning, Spam body, Human body, Shared Page Ending. I also use postback on real pages to show validation errors while keeping the user data but that would make the answer even harder to follow. – Dave S Oct 04 '19 at 22:27
  • The first ?> (7th line down) doesn't seem to close anything. Am I misunderstanding? – user1551817 Oct 04 '19 at 22:33
  • 1
    No, that was me omitting the first line, ` – Dave S Oct 04 '19 at 23:02
  • 1
    you can make your life a lot easier by changing that honeypot condition to `if (filter_input(INPUT_POST, 'contact_me_by_fax_only', FILTER_SANITIZE_NUMBER_INT) === 1)` and also add some security to the method for capturing that variable. – Lawrence Johnson Oct 04 '19 at 23:45
  • I'm still not quite getting the order of things I'm afraid. I've updated my question to include more of my code. – user1551817 Oct 08 '19 at 15:32