Tutorial How to Easily Make Captcha in Laravel 8

Tutorial How to Easily Make Captcha in Laravel 8

Admin
Admin・ 10 Agustus 2021
10 min read ・ 6502 views

Laravel 8 Captcha - Captcha is a form of test or challenge response test used in the world of information technology to ensure that answers are not generated by a computer or machine. This process usually involves a computer or server asking the user to complete a simple challenge that can be generated and assessed by the computer or server. Since other computers or robots cannot solve the Captcha, any user who can give the correct answer will be considered a human. Therefore, this challenge is referred to as a back turing test, because it is administered by a machine and shown to humans, as opposed to a standard turing test which is usually administered by humans and shown to a machine. Captchas generally use letters or numbers from a distorted image that appears on the screen.

The term "CAPTCHA" (derived from the English word "capture") was coined in 2000 by Luis von Ahn, Manuel Blum, Nicholas J. Hopper (all from Carnegie Mellon University) and John Langford (IBM). This term is an English acronym for "Completely Automated Public Turing Test to Tell Computers and Humans Apart".

Source: Wikipedia

In this article I will share how to create or apply a captcha to the register feature in laravel 8 to ensure that the register is a human. In this experiment, I will use the laravel captcha package from Mewebstudio.

Let's Start Coding Making Captcha in Laravel 8

Alright, after understanding what a captcha is, it's time for us to code to create or apply a captcha in the laravel 8 register feature.

Install Laravel

composer create-project laravel/laravel laravel-captcha

Alright, let's start by installing the latest version of laravel (currently version 8.47.0). Run the above command to install laravel via composer.

Install Laravel UI Package

composer require laravel/ui
php artisan ui bootstrap --auth
npm install
npm run dev

In this experiment, we will use laravel ui to create authentication. Here we will use authentication because we will use captcha for the register feature. So, if the user cannot complete the captcha then the user cannot register. Run the above commands sequentially on the terminal.

Create Database

Then after the laravel ui package install process is complete, continue by creating a new database to accommodate user data. Since I use xampp as my local server, I will create a new database with the name laravel-captcha in phpMyAdmin. Don't forget to match the DB_DATABASE in the .env file with the database name you just created and run php artisan migrate.

Install Laravel Captcha Package

composer require mews/captcha

After the laravel install process is complete, now we install the captcha package from mewebstudio. Run the above command in the terminal to install the captcha package.

Setup Captcha Package

To be able to use captcha package in laravel project, we have to register service provider in config/app. Please open the config/app file, then add the captcha service provider and aliases like the example below.

'providers' => [

        .......
        .......
        .......
        /*
         * Package Service Providers...
         */
        Mews\Captcha\CaptchaServiceProvider::class,

        .....
        .....
    ],
'aliases' => [
       ......
       ......
        'Captcha' => Mews\Captcha\Facades\Captcha::class,
       ......
    ],

Configuration

php artisan vendor:publish

For advanced configuration, we can publish service provider for Mews\Captcha\CaptchaServiceProvider::class,. The captcha configuration file is located in config/captcha. In this captcha file, we can adjust the captcha according to the needs of our Laravel application or website.

Add Route

Route::get('/reload-captcha', [App\Http\Controllers\Auth\RegisterController::class, 'reloadCaptcha']);

The next step is to add a new route by setting the url /reload-captcha. What is this route for? so we will call this route when there is a new captcha request or reload captcha. This route will be directed to the RegisterController or to be precise in the reloadCaptcha function. For now, the reloadCaptcha function doesn't exist in our RegisterController.php yet, so we'll create it in the next step.

Edit Auth/RegisterController.php

protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
            'captcha' => ['required','captcha'],
        ]);
    }
   
    public function reloadCaptcha()
    {
        return response()->json(['captcha'=> captcha_img()]);
    }

Now open the file App/Http/Controller/RegisterController.php. Here we will add a new validation for captcha, so for now our validator function will be like the code above with the addition of captcha. Then we will create a new function to reload the captcha, the reloadCaptcha function can be seen as well as the code above.

Edit Auth/register.blade.php

@extends('layouts.app')
@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Register') }}</div>
                <div class="card-body">
                    @if ($errors->any())
                    <div class="alert alert-danger">
                        <ul>
                            @foreach ($errors->all() as $error)
                            <li>{{ $error }}</li>
                            @endforeach
                        </ul>
                    </div>
                    <br />
                    @endif
                    <form method="POST" action="{{ route('register') }}">
                        @csrf
                        <div class="form-group row">
                            <label for="name" class="col-md-4 col-form-label text-md-right">{{ __('Name') }}</label>
                            <div class="col-md-6">
                                <input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name') }}" required autocomplete="name" autofocus>
                                @error('name')
                                <span class="invalid-feedback" role="alert">
                                <strong>{{ $message }}</strong>
                                </span>
                                @enderror
                            </div>
                        </div>
                        <div class="form-group row">
                            <label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
                            <div class="col-md-6">
                                <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email">
                                @error('email')
                                <span class="invalid-feedback" role="alert">
                                <strong>{{ $message }}</strong>
                                </span>
                                @enderror
                            </div>
                        </div>
                        <div class="form-group row">
                            <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">
                                @error('password')
                                <span class="invalid-feedback" role="alert">
                                <strong>{{ $message }}</strong>
                                </span>
                                @enderror
                            </div>
                        </div>
                        <div class="form-group row">
                            <label for="password-confirm" class="col-md-4 col-form-label text-md-right">{{ __('Confirm Password') }}</label>
                            <div class="col-md-6">
                                <input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
                            </div>
                        </div>
                        <div class="form-group row">
                            <label for="captcha" class="col-md-4 col-form-label text-md-right">Captcha</label>
                            <div class="col-md-6 captcha">
                                <span>{!! captcha_img() !!}</span>
                                <button type="button" class="btn btn-danger" class="reload" id="reload">
                                &#x21bb;
                                </button>
                            </div>
                        </div>
                        <div class="form-group row">
                            <label for="captcha" class="col-md-4 col-form-label text-md-right">Enter Captcha</label>
                            <div class="col-md-6">
                                <input id="captcha" type="text" class="form-control" placeholder="Enter Captcha" name="captcha">
                            </div>
                        </div>
                        <div class="form-group row mb-0">
                            <div class="col-md-6 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                {{ __('Register') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
@push('scripts')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
    $('#reload').click(function () {
        $.ajax({
            type: 'GET',
            url: 'reload-captcha',
            success: function (data) {
                $(".captcha span").html(data.captcha);
            }
        });
    });
</script>
@endpush

Then we will go to register.blade.php file, here we will add form group to display captcha and create input form for captcha. In addition, we also added an alert danger to display a validation message if the entered captcha does not match. We also create an AJAX script to call the reload-captcha route when the button with id reload is clicked. Note that here we are adding @push('scripts'), so we also need to add @stack('scripts') in the layouts/app.blade.php file before the </body> tag.

Captcha Testing in Laravel 8

laravel captcha

After going through a long process starting from installing laravel, laravel ui package, laravel captcha package to displaying captcha in the register form, now is the time for testing. Please try by opening the URL 127.0.0.1:8000/register or laravel-captcha.test/register, on the Enter Captcha form try to enter text that does not match the displayed captcha, then the result is that we cannot continue registering because the entered captcha is incorrect.

Conclusion

In this article, we have both learned how to easily create or apply a captcha to the register feature in laravel 8 by using the laravel captcha package from mewebstudio. With this package, we can easily apply captcha and provide security for our website from robot attacks or user spam.

That's all for this article, if there are criticisms, suggestions or anything that you want to discuss, please write a comment in the comment form provided below. See you.

Device illustrations by Storyset

Tinggalkan Komentar
Loading Comments