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:
- Create a route in
routes.php
to hold our form:Route::get('myform', function() { return View::make('myapp'); });
- Create a view in our
app/view
directory named asmyform.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() ?>
- Create a route in our
routes.php
file to handle thepost
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(); }));
- In our
routes.php
file, create a custom validation:Validator::extend('honey_pot', function($attribute, $value,$parameters) { return $value == ''; });
- 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.