While submitting a form it is required to validate the data and the form submission. But, what if any bot or program will submit the form automatically without any human interaction? That time it will hamper the application by submitting the form again and again. This can be prevented using captcha in Laravel. There are so many packages are available for captcha validation. In this post, I will be implementing the invisible captcha in Laravel 8.
Prerequisities
If you are going to create a new project setup in Laravel 8 then you must require the following configuration.
- PHP >= 7.3
- MySQL (version > 5)
- Apache/Nginx Server
- VS Code Editor
- Composer
Once, you are done, then let’s create a new project.
Create a Project For Captcha in Laravel 8
I am going to create the project using the composer. You can also use the Laravel installer. If you are ready to go then hit the below command in the terminal.
composer create-project --prefer-dist laravel/laravel captcha
The above command will create a folder and then it will install the Laravel 8. It will take a couple of minutes to install.
Once, it is finished, let’s create a database first. Then we will connect it with the application
Create Authentication in Laravel 8 Using Laravel Breeze
Create and Configure Database
Firstly, create a database in MySQL. Here, I am using the command line for creating the database.
CREATE DATABASE laravel_captcha;
After creating the database, let’s connect it to the application. Just open the .env file and then configure the database settings.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_captcha
DB_USERNAME=root
DB_PASSWORD=root
After connecting the database, we will install the invisible reCAPTCHA in this project.
Install Invisible reCAPTCHA in Laravel 8
Invisible reCAPTCHA package is open source available on Github. You can easily install it inside the project.
composer require albertcht/invisible-recaptcha
You can find the above command on the Github. Here, I am installing it inside the project.
After the successful installtion, it will require to register this package in the providers array.
So, to do that, you will require to go to the config/app.php file.
'providers' => [
...
...
...
...
AlbertCht\InvisibleReCaptcha\InvisibleReCaptchaServiceProvider::class,
],
Here, I have registered the providers in the bottom of the array.
User Authentication in Laravel 8 Using UI Auth Package
Add Invisible reCAPTCHA Configuration in Laravel
Here, you have to add the below configuration settings in the .env file of the project.
INVISIBLE_RECAPTCHA_SITEKEY={siteKey}
INVISIBLE_RECAPTCHA_SECRETKEY={secretKey}
INVISIBLE_RECAPTCHA_BADGEHIDE=false
INVISIBLE_RECAPTCHA_DATABADGE='bottomright'
INVISIBLE_RECAPTCHA_TIMEOUT=5
INVISIBLE_RECAPTCHA_DEBUG=false
For the site key and the secret key, you will have to register a website in the Google reCAPTCHA. You will require to register and get the site key and the secret key. You will have to put the domain name, Google doesn’t understand the localhost. So, if you put localhost then it won’t allow you to use the captcha. In my case, I have deployed this project on the domain and then registered the domain name to access the site key and secret key.
Remove Uploaded Image in Laravel 8 From Public Folder
Create Controller For Captcha in Laravel
Here, I will create a controller for the User. We have the default model for the User. Here, I am not going to insert the form data into the database. I will just read the form data into the controller with the captcha.
php artisan make:controller UserController
After creating the controller, let’s put some code there.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class UserController extends Controller
{
public function index() {
return view('signup');
}
public function store(Request $request) {
// validating re-captcha
$this->validate($request, [
'g-recaptcha-response' => 'required|captcha'
]);
return $request->all();
}
}
In the above code, there are two functions-
- The first function is simply loading a view. (We will create this view in the next step)
- The next function is to read the form data which will be coming through the view. Here, I have created a validation rule for captcha. So, if the form will submit automatically without any human interaction then it will prevent it.
I will show you the both functionality to submit the form. So, let’s create routes first according to the above functions.
How to Configure PHPMailer in Laravel 8 For Sending Email
Create Routes For the UserController
Here, you will require to add the routes in the web.php file.
<?php
use App\Http\Controllers\UserController;
use Illuminate\Support\Facades\Route;
Route::get('users', [UserController::class, 'index'])->name('users');
Route::post('users', [UserController::class, 'store'])->name('users');
After adding the routes, we will create the view for implementing the invisible captcha in Laravel. The view will contain a very basic form. On that form, I will be implementing the invisible reCAPTCHA functionality. So, let’s do that.
Dynamic Email Configuration in Laravel 8 For Sending Email
Create a View for Invisible reCAPTCHA
Create a view and name it signup.blade.php. Then add the below snippet there.
<!doctype html>
<html lang="en">
<head>
<title>Invisible reCAPTCHA in Laravel 8</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<div class="container py-5">
<div class="row">
<div class="col-xl-6 col-lg-6 col-sm-12 col-12 m-auto">
{{-- display validation errors --}}
@if(count($errors) > 0)
@foreach($errors->all() as $error)
<small class='text-danger'>{{$error}}</small>
@endforeach
@endif
<form action="{{route('users')}}" method="POST" id="regForm">
@csrf
{{-- enable captcha for the form --}}
@captcha
<div class="card">
<div class="card-header">
<h5 class="card-title font-weight-bold">Invisible reCAPTCHA in Laravel 8</h5>
</div>
<div class="card-body">
<div class="form-group">
<input type="text" name="name" class="form-control" placeholder="Name">
</div>
<div class="form-group">
<input type="email" name="email" class="form-control" placeholder="Email">
</div>
<div class="form-group">
<input type="password" name="password" class="form-control" placeholder="Password">
</div>
</div>
<div class="card-footer">
<div class="form-group">
<button type="submit" class="btn btn-success">Save</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk="crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<script>
$(document).ready(function() {
$("#regForm").submit();
});
</script>
</body>
</html>
- In the above snippet, I have created a registration form with some fields and a submit button.
- I have put
@captcha
in the form. It will enable the captcha for this view. - At the bottom, I have created a jQuery script for submitting the form automatically on page load.
So, save and run the application to check the result.
Here, the reCAPTCHA has been enabled for the form. When you will hover it, it will show the complete captcha as showing below.
Firstly, let’s try submitting the form using the jQuery submit() function on the load event. In this case, we will not hit the submit button manually. So, firstly, I checked it without the form validation.
When I removed the validation from the controller then it automatically submitted the form.
But, when I enabled the captcha validation in the controller, it displayed the error message as showing below.
Here, you can see the captcha prevented from the auto submit of the form. Now, you can disable the jQuery script to submit the form. Now, you can try manually submitting the form. It will detect the human interaction with the form and it will allow submitting the form.
Create REST API in Laravel 8 Using JWT Authentication
How to Make Invisible to reCAPTCHA
Now, coming to the feature of this package, in the configuration setting (.env file).
INVISIBLE_RECAPTCHA_SITEKEY={{YOUR-SITE-KEY}}
INVISIBLE_RECAPTCHA_SECRETKEY={{YOUR-SECRET-KEY}}
INVISIBLE_RECAPTCHA_BADGEHIDE=false
INVISIBLE_RECAPTCHA_DATABADGE='bottomright'
INVISIBLE_RECAPTCHA_TIMEOUT=5
INVISIBLE_RECAPTCHA_DEBUG=false
If you want to make it invisible then you have to make it true to badgehide setting. Just like this –
INVISIBLE_RECAPTCHA_BADGEHIDE=true
It will make invisible from the form. But, it will work same as working now. It will prevent the auto form submit.
Conclusion
We implemented the reCAPTCHA in the Laravel 8 application. It is a very interesting feature of Google. The captcha prevents the auto form submit using the validation. It checks and detects the hit of the form submit a request. So, we have seen both cases in this post. I tried form submission using the jQuery script. When I enabled the validation then it prevented the form submit. So, I hope you can implement it in your real projects like the contact form.
skl says
I’m getting this error. any idea why?
array_key_exists() expects parameter 2 to be array, null given (View: C:\xampp\htdocs\laravel\resources\views\auth\passwords\email.blade.php)
Umesh Rana says
You are using array_key_exists() function. This function takes two arguments.
Syntax: array_key_exists (string|int $key, array $array): bool
The first argument is the key that you want to search. The data type can be string or int.
The second argument is the array in which you want to search the specific key.
In the result, it will return the boolean like true or false if the key exists or not.