Tuesday, April 3, 2012

How to Create a Honey Pot with CodeIgniter

Most websites will use some sort of text captcha to stop spam bots that autofill webforms.  Although to most people, filling out the captcha may not be a big deal, but it can be a small step that may cause some users to not use the form.

Here is where the honey pot comes in.  A honey pot is a hidden form field in your form that human users cannot see, but bots that scour websites for form fields to autofill will see it and can enter a value for it.  Then, when the bot tries to submit the form and spam your website, you can use form validation to stop any submits that has the honey pot filled in. Read more about honey pots here.

This lesson will give CodeIgniter users an easy way to use honey pots using the form validation class.

Setup
Set up a clean CI installation.  Then go to your autoload file in your config folder.

Controller
Create a Controller named honey.php in your controllers folder.

Create the controller class, then add an index function that loads a view with the form you will create.  In my case I named my view "form.php".
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');


class Honey extends CI_Controller
{
    function index()
    {
        $this->load->view('form');
    }
}

View
Create a view that contains your form code.

Here is mine:
 <html>

<body>

<h2>Generic Form</h2>

<form name="input" action="honey_submit" method="post">
    <p>Name:
        <input type="text" name="name" id="name" />
    </p>
  
    <p>Comment:
        <input type="textbox" name="comment" id="comment" />
    </p>

  
 <input type="hidden" name="honeypot" id="honeypot" />
  
    <p>
        <input type="submit" />
    </p>
</form>

</body>
</html>
Notice the hidden input field named honeypot.

As you can see, the action submits it to a function in the controller called  'honey_submit'. So, create that function in your 'honey' controller file.

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');


class Honey extends CI_Controller
{
    function index()
    {
        $this->load->view('form');
    }

    function honey_submit()
    {
      
    }

}
(Bold is new code)

Parse Data

 To access the data that was sent:

    function honey_submit()
    {
       $this->input->post('name');
      $this->input->post('comment');
      $this->input->post('honeypot');

    }

Load Form Validation Class
  function honey_submit()
    {
        $this->load->library('form_validation');
      
        $this->input->post('name');
        $this->input->post('comment');
        $this->input->post('honeypot');
    }

Set Validation Criteria

Let's make the name and comment required.
function honey_submit()
    {
        $this->load->library('form_validation');
       
        $this->form_validation->set_rules('name', 'Name', 'required');
        $this->form_validation->set_rules('comment', 'Comment', 'required');

       
        $this->input->post('name');
        $this->input->post('comment');
        $this->input->post('honeypot');      
      }
Now, here is how you can use the Form Validation class to stop spambots and output an error message.

Using the Form Validation rule that calls a callback function, you can make a simple to see if the form is filled or not.
    public function honey_submit()
    {
        $this->load->library('form_validation');
       
        $this->form_validation->set_rules('name', 'Name', 'required');
        $this->form_validation->set_rules('comment', 'Comment', 'required');
        $this->form_validation->set_rules('honeypot', 'Honeypot', 'callback_bot_test');
       
        $this->input->post('name');
        $this->input->post('comment');
        $this->input->post('honeypot');
    }
The 'set_rules' function needs three arguments: the input name from the form, any name used in the error message, and a function to use as the call back function.

The name of the callback function are the characters after the 'callback_' part of the third argument of the 'set_rules' function, i.e. 'bot_test'.

Now we need to create the call back function in the 'honey' controller:
public function bot_test($input)
    {
        if ($input)
        {
            $this->form_validation->set_message('bot_test', 'No bots allowed!');
            return FALSE;
        }
        else
        {
            return TRUE;
        }
    }
The $input argument is whatever was sent from the hidden honeypot form field.

All we do is test that it exists.  Then we set an error message.

Create 'form_submitted' View
<html>

<body>

<p>
<?php if( validation_errors() ): ?>
    <?php echo validation_errors();?>
<?php else: ?>
    Form submitted!
    <p>
    Name:
    <?php echo $name; ?>
    </p>
    <p>
    Comment:
    <?php echo $comment; ?>
    </p>
<?php endif; ?>

</p>

<p>

</p>
</body>

</html>
 All we did here is check if there were any validation errors.  If there were, we echo the error messages.  If everything is OK, we tell the user that the form has been submitted and we echo out the name and comment that they submitted.

Run Validation and Load the New View
This is a very important step.  In your 'honey' controller and in the 'honey_submit' function, run the validation test.
public function honey_submit()
    {
        $this->load->library('form_validation');
       
        $this->form_validation->set_rules('name', 'Name', 'required');
        $this->form_validation->set_rules('comment', 'Comment', 'required');
        $this->form_validation->set_rules('honeypot', 'Honeypot', 'callback_bot_test');
       
        $this->form_validation->run();     
  

        $this->input->post('name');
        $this->input->post('comment');
        $this->input->post('honeypot');
       
    }
This runs the validation tests and outputs any errors.

Now, load the view, passing the name and comment to the view.
public function honey_submit()
    {
        $this->load->library('form_validation');
       
        $this->form_validation->set_rules('name', 'Name', 'required');
        $this->form_validation->set_rules('comment', 'Comment', 'required');
        $this->form_validation->set_rules('honeypot', 'Honeypot', 'callback_bot_test');
       
        $this->form_validation->run();       

        $data['name'] = $this->input->post('name');
        $data['comment']= $this->input->post('comment');

        $this->input->post('honeypot');
       
        $this->load->view('form_submitted', $data);
    }
Test and Finish
Now, to test the honeypot, go the the 'form' view and change the html for the hidden input and give it a value:

<input type="hidden" name="honeypot" value="anyvalue" id="honeypot" />
Now try to submit the form.

You should get an error message 'No bots allowed!' .

Go back and delete the value section of the hidden input and you should be ready to go!

Conclusion
A honey pot is not 100%, but it does stop many of the bots.

A few good reasons to use the callback function to validate the input:
-It sets an error message automatically.
-You can do other things in the call back function, like record the IP address of a spammer.

Congratulations!  You now know how to create a honey pot using CodeIgniter!

Monday, April 2, 2012

Working on a website...

For the past few weeks I have been working on a website (www.f5stormrooms.com) for Elysa's Dad.  Although it is challenging, it is a great opportunity to have something I've built out in world wide web. 

I've gone all out and have been making a small content management system for her Dad to be able to create a gallery, add pictures, and post news and updates.  It has been a great learning opportunity! 

I have found that there are many details to make everything perfect, from user validation to error handling. 

I have to say I am almost complete with the PHP.  After that I am going to style the pages, and then add some javascript functionality to make some things friendlier. 

I'll keep all my loyal readers updated!

P.S.!

Follow me on twitter!

Sunday, April 1, 2012

Getting in shape...

Elysa motivated me to finally get up and run.  I better keep at it if I want get into shape.

It's nice to feel that burn in your lungs when you haven't worked them hard in a long time.

My goal is to be able to run at least 3 miles without feeling like I am going to die! 

Thanks to Elysa for snapping a picture of me!