algolia search

Tìm thấy x bài viết trong xms.

Tích hợp Google reCAPTCHA v2  vào dự án Laravel

Tích hợp Google reCAPTCHA v2 vào dự án Laravel


1. Captcha là gì?

CAPTCHA là một công cụ xác thực trên website để đảm bảo rằng website của bạn không bị SPAM bằng một công cụ tự động. Theo truyền thống captcha là một hình ảnh với dòng các chữ khó phân tích bởi một chương trình tự động, người dùng phải nhập lại dòng chữ giống với chữ trên hình ảnh để chứng minh họ không phải là cái máy. CAPTCHA truyền thống có thể đáp ứng được yêu cầu đặt ra tuy nhiên đôi khi khá phiền phức, các dòng chữ CAPTCHA đôi khi rất khó đọc đối với người dùng.

Hình ảnh một CAPTCHA truyền thống
Hình ảnh một CAPTCHA truyền thống

2. reCaptcha

reCAPTCHA là một dịch vụ CAPTCHA của Google miễn phí giúp website của bạn chống lại SPAM, các đăng ký độc hại, hoặc các hình thức tấn công khác, nơi mà các chương trình tấn công cố gắng che giấu bản thân tạo ra các hành vi giống con người. reCAPTCHA với giao diện đơn giản, có thể dễ dàng thêm vào blog, forum hoặc website của bạn,...

Hình minh họa dưới đây mô tả nguyên tắc hoạt động của reCAPTCHA:

3. Tích hợp reCaptcha vào Laravel

3.1 Đăng ký site key và secret key

Truy cập trang https://www.google.com/recaptcha/admin và tiến hành đăng ký

Nếu lười bạn cũng có thể dùng site key và secret key TEST do Google cung cấp, nhưng khi public thì nhớ đăng ký nhé.

  • site key: 6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
  • secret key: 6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe

3.2 Tạo project Laravel

Chú ý: nếu bạn đã có sẵn project Laravel rồi thì bỏ qua bước này đến bước 3.3 nhé.

composer create-project --prefer-dist laravel/laravel recaptcha

3.3 Tạo database recaptcha

Mở file .env và sửa lại thông tin database

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=recaptcha
DB_USERNAME=root
DB_PASSWORD=

3.4 Run migrate

Trong file recaptcha\app\Providers\AppServiceProvider.php function boot() bạn thêm dòng sau để chạy migrate khỏi bị lỗi

    public function boot()
    {
        \Schema::defaultStringLength(191);
    }

Chạy artisan command sau

php artisan migrate

Run migrate mà gặp lỗi 1071 - Specified key was too long; max key length is 767 bytes thì xem bài viết này nhé Lỗi Laravel: 1071 - Specified key was too long; max key length is 767 bytes

3.5 Cài gói guzzlehttp

Để xác minh phản hồi của người dùng, chúng ta cần gửi request đến Google api nên cần dùng gói này. Thêm gói này vào composer

cd recaptcha
composer require guzzlehttp/guzzle

3.6 Khai báo site key và secret key Google reCaptcha

Mở file .env và thêm dòng sau vào cuối file

GOOGLE_RECAPTCHA_KEY=6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
GOOGLE_RECAPTCHA_SECRET=6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe

3.7 Tích hợp reCaptcha vào validate form đăng ký

Chạy lên artisan command sau:

php artisan make:auth

Trong recaptcha\resources\views\layouts\app.blade.php phần<head> tag thêm đoạn script này vào:

<script src="https://www.google.com/recaptcha/api.js" async defer></script>

Trong recaptcha\resources\views\auth\register.blade.php ta chỉnh sửa 1 chút bằng cách thêm tag Google reCaptcha vào

@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">
                    <form method="POST" action="{{ route('register') }}" aria-label="{{ __('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{{ $errors->has('name') ? ' is-invalid' : '' }}" name="name" value="{{ old('name') }}" required autofocus>

                                @if ($errors->has('name'))
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $errors->first('name') }}</strong>
                                    </span>
                                @endif
                            </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{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" required>

                                @if ($errors->has('email'))
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $errors->first('email') }}</strong>
                                    </span>
                                @endif
                            </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{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" required>

                                @if ($errors->has('password'))
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $errors->first('password') }}</strong>
                                    </span>
                                @endif
                            </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>
                            </div>
                        </div>

                        <!-- Google reCaptcha -->
                        <div class="g-recaptcha" id="feedback-recaptcha" data-sitekey="{{ env('GOOGLE_RECAPTCHA_KEY')  }}"></div>
                        <!-- End Google reCaptcha -->

                        <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

Truy cập http://localhost/recaptcha/public/register bạn sẽ thấy như thế này là ok

3.8 Validate phía Server

Sau khi tích vào nút I'm not a robot và nhấn nút Register sẽ gửi request lên server để xử lý.

Tạo mới reCaptcha validate rule

php artisan make:rule ValidRecaptcha

Trong file recaptcha\app\Http\Controllers\Auth\RegisterController.php function validator thêm 'g-recaptcha-response' => ['required', new \App\Rules\ValidRecaptcha]

 

    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:6|confirmed',
            'g-recaptcha-response' => ['required', new \App\Rules\ValidRecaptcha]
        ]);
    }

 Tiến hành định nghĩa rule cho class ValidRecaptcha (recaptcha\app\Rules\ValidRecaptcha.php)

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;
use GuzzleHttp\Client;

class ValidRecaptcha implements Rule
{
    /**
     * Create a new rule instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        // Khởi tạo http client
        $client = new Client([
            'base_uri' => 'https://google.com/recaptcha/api/'
        ]);

        // Gửi dữ liệu đến cho google recaptcha xử lý
        $response = $client->post('siteverify', [
            'query' => [
                'secret' => env('GOOGLE_RECAPTCHA_SECRET'),
                'response' => $value
            ]
        ]);

        // Google reCaptcha trả về kết quả đúng/sai
        return json_decode($response->getBody())->success;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        // Message thông báo khi kết quả trả về là sai
        return 'ReCaptcha verification failed.';
    }
}

Done!

Bạn thử đăng ký user mới thử xem ok chưa nhé!

Source code mình đã up lên github, bạn nào cần có thể checkout về xem lại nha

https://github.com/nguyentranchung/laravel-recaptcha-sample 

Đánh giá bài viết

Thích thì like
Tích hợp Google reCAPTCHA v2 vào dự án Laravel
5/5 1 votes

Bình luận

Hiển thị bình luận Facebook