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.
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
Ủng hộ Chung Nguyễn Blog
Chung Nguyễn Blog sử dụng FlashVPS - Dịch vụ quản trị máy chủ chuyên nghiệp để quản lý VPS
#FlashVPS là dịch vụ cloud panel trên nền tảng web hỗ trợ khách hàng:
- * Quản lý máy chủ số lượng nhiều
- * Không có kinh nghiệm quản lý máy chủ
- * Thích sử dụng giao diện web đơn giản, trực quan hơn terminal
- * Quá nhàm chán với việc ghi nhớ và lặp lại việc gõ các câu lệnh
- * Muốn tự động hóa mọi thao tác
- * Muốn tiết kiệm thời gian quản trị máy chủ
- * Muốn tiết kiệm tiền bạc, nhân lực quản trị máy chủ 👉 https://flashvps.dev
Các bài viết trên website thường xuyên được đăng tải và cập nhật trên trang Facebook Chung Nguyễn Blog hãy tặng cho Chung một LIKE nhé! Mãi yêu các bạn!
813 👍
Bình luận