Laravel Application Development Cookbook
上QQ阅读APP看书,第一时间看更新

Adding a honey pot to a form

A sad reality of the Web is that there are "spam bots" that search the web and look for forms to submit spam to. One way to help combat this is to use a technique called a honey pot. In this recipe, we'll create a custom validation to check for spam submissions.

Getting ready

For this recipe, we just need a standard Laravel installation.

How to do it...

To complete this recipe, follow these steps:

  1. Create a route in routes.php to hold our form:
    Route::get('myform', function()
    {
        return View::make('myapp');
    });
  2. Create a view in our app/view directory named as myform.php and add the form:
    <h1>User Info</h1>
    <?php $messages =  $errors->all('<p style ="color:red">:message</p>') ?>
    <?php
    foreach ($messages as $msg)
    {
        echo $msg;
    }
    ?>
    <?= Form::open() ?>
    <?= Form::label('email', 'Email') ?>
    <?= Form::text('email', Input::old('email')) ?>
    <br>
    <?= Form::label('username', 'Username') ?>
    <?= Form::text('username', Input::old('username')) ?>
    <br>
    <?= Form::label('password', 'Password') ?>
    <?= Form::password('password') ?>
    <?= Form::text('no_email', '', array('style' =>'display:none')) ?>
    <br>
    <?= Form::submit('Send it!') ?>
    <?= Form::close() ?>
  3. Create a route in our routes.php file to handle the post data, and validate it:
    Route::post('myform', array('before' => 'csrf', function()
    {
        $rules = array(
            'email'    => 'required|email',
            'password' => 'required',
            'no_email' => 'honey_pot'
        );
        $messages = array(
            'honey_pot' => 'Nothing should be in this field.'
        );
        $validation = Validator::make(Input::all(), $rules,$messages);
    
        if ($validation->fails())
        {
            return Redirect::to('myform')->withErrors($validation)->withInput();
        }
    
        return Redirect::to('myresults')->withInput();
    }));
  4. In our routes.php file, create a custom validation:
    Validator::extend('honey_pot', function($attribute, $value,$parameters)
    {
        return $value == '';
    });
  5. Create a simple route to use for a success page:
    Route::get('myresults', function()
    {
        return dd(Input::old());
    });

How it works...

We first create a fairly simple form; since we aren't passing any parameters to Form::open(), it will POST the data to the same URL. In the form, we create a field that's designed to be empty, but hide it from the user using CSS. By naming it as something with the word email in it, many spam bots will mistake it for an email field and try to populate it.

We then create a route to accept the post data and validate it, along with having a csrf filter added before the route. We add a custom validation rule to our no_email field, which will make sure that field stays empty. We also create an error message for that rule in the $messages array.

Next, we actually create our custom validation rule in the routes file. This rule will get the value from the form field and return TRUE if the value is empty.

Now, if a bot tries to fill in the entire form, it will not validate since that extra field is designed to stay empty.

There's more...

One alternative to creating a custom validation is to use the rule size: 0, which will make sure the honey_pot field is exactly 0 characters in length. However, this method keeps the validation check much simpler.

We might also want to redirect any honey pot errors to another page that doesn't have a form. That way, any automatic form submission scripts won't continue to try and submit the form.