Tích hợp Google reCAPTCHA trong Laravel
NỘI DUNG BÀI VIẾT
Trong các tính năng như liên hệ, đăng ký, bình luận bài viết, yêu cầu khảo sát… đôi khi chúng ta cần xác thực xem các hành động nhập dữ liệu là do người dùng thật sự hay do một robot nào đó. Đặc biệt khi càng ngày tình trạng spam diễn ra mạnh mẽ việc xác thực này là cần thiết. Có rất nhiều cách xác thực như gửi email, sms, captcha… tuy nhiên, với những nơi cần xác định xem là người dùng hay robot nhanh thì captcha là giải pháp tốt nhất.
Captcha là gì?
Captcha (Completely Automated Public Turing test to tell Computers and Humans Apart) tạm dịch là Phép thử Turing công cộng hoàn toàn tự động để phân biệt máy tính với người được Đại học Carnegie Mellon công bố. Captcha là một quá trình máy tính yêu cầu người dùng hoàn thành một kiểm tra đơn giản để đánh giá, bất kỳ người nào nhập vào lời giải đúng được xem là con người. Một hệ thống tích hợp captcha sẽ có các đặc điểm sau:
- Đa số con người có thể giải được captcha một cách dễ dàng.
- Các thuật toán kết hợp xử lý máy tính không thể giải được.
Google reCaptcha là một dịch vụ của Google tích hợp được vào bất kỳ chỗ nào muốn xác định xem hành động nào đó là do con người hay máy tính tạo ra. Khi bạn lướt web, chắc chắn bạn đã từng gặp những ô captcha với chữ loằng ngoằng.

Các cải tiến mới đây giúp cho Google reCaptcha đã dần trở lên vô hình với người dùng, các thuật toán mới giúp cho Google xác định được hành vi do con người hay máy tính một cách chính xác mà không cần đến những ký tự loằng ngoằng như trước, trừ khi Google không thể xác định được, các cách thức xác định cũ như nhập chữ, click hình ảnh liên quan chủ đề mới được sử dụng.

Tích hợp Google reCAPTCHA xác định người hay máy trong các ứng dụng Laravel
Đăng ký Google reCAPTCHA
Trước tiên, bạn cần có một tài khoản Google để tạo Google reCAPTCHA cho website, vào trang đăng ký click vào Get reCAPTCHA. Điền thông tin vào form đăng ký.

Như vậy bạn đã tạo ra một reCAPTCHA để sử dụng cho website. Chúng ta sẽ thấy Site key và Secret key được sử dụng để tích hợp reCAPTCHA.

Thiết lập cấu hình, tạo class xử lý reCAPTCHA
Hai khóa được tạo ra trong bước đăng ký reCAPTCHA sẽ được đưa vào ứng dụng Laravel thông qua .env hoặc config/app.php
GOOGLE_RECAPTCHA_KEY=6LcqPUIoiUNFAH_5KVxMGYDu76BS62jBqjJ3dRU1 GOOGLE_RECAPTCHA_SECRET=6LcqPUIoiUNFAIcVBrk)OD8nce6ASMPweWzQri-4
Các key ở trên chỉ là demo, bạn nên tạo key riêng cho reCAPTCHA của bạn. Chúng ta quay lại ví dụ đăng ký người dùng trong bài Laravel Authentication, form đăng ký có email chúng ta có thể dùng xác thực qua email đảm bảo hơn, tuy nhiên có nhiều website muốn người dùng đăng ký nhanh không cần qua bước xác thực email lằng nhằng mà chỉ cần xác định đúng là người không phải máy thôi. Chúng ta sửa đổi lại view để đăng ký người dùng trong file resources/views/auth/register.blade.php:
@extends('layouts.default')
@section('title', 'Đăng ký - Allaravel.com')
@section('link-header')
<script src='https://www.google.com/recaptcha/api.js'></script>
@endsection
@section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Đăng ký thành viên</div>
<div class="panel-body">
<form class="form-horizontal" role="form" method="POST" action="{{ route('register') }}">
{{ csrf_field() }}
<div class="form-group{{ $errors->has('name') ? ' has-error' : '' }}">
<label for="name" class="col-md-4 control-label">Họ và tên</label>
<div class="col-md-6">
<input id="name" type="text" class="form-control" name="name" value="{{ old('name') }}" required autofocus>
@if ($errors->has('name'))
<span class="help-block">
<strong>{{ $errors->first('name') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
<label for="email" class="col-md-4 control-label">Địa chỉ email</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control" name="email" value="{{ old('email') }}" required>
@if ($errors->has('email'))
<span class="help-block">
<strong>{{ $errors->first('email') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
<label for="password" class="col-md-4 control-label">Mật khẩu</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control" name="password" required>
@if ($errors->has('password'))
<span class="help-block">
<strong>{{ $errors->first('password') }}</strong>
</span>
@endif
</div>
</div>
<div class="form-group">
<label for="password-confirm" class="col-md-4 control-label">Nhập lại mật khẩu</label>
<div class="col-md-6">
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-4 col-md-6">
<div class="g-recaptcha" data-sitekey="6LcqPUIoiUNFAH_5KVxMGYDu76BS62jBqjJ3dRU1" data-callback="YourOnSubmitFn"></div>
</div>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-4">
<button type="submit" class="btn btn-primary">
Đăng ký
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Code language: HTML, XML (xml)
Chúng ta thay đổi default template (resources/views/layouts/defautl.blade.php) đi một chút để có thể insert các file css, javascript nếu muốn trong view, thêm @yield(‘link-header’):
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<meta name="description" content="">
<meta name="author" content="">
<title>All Laravel - @yield('title')</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Custom styles for this template -->
<link href="http://getbootstrap.com/examples/sticky-footer-navbar/sticky-footer-navbar.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<
![endif]-->
@yield('link-header')
</head>
<body>
@include('layouts.menu')
<!-- Begin page content -->
<div class="container">
<div class="page-header">
<h1>Môi trường test Laravel cho website allaravel.com</h1>
</div>
<p class="lead">
@yield('content')
</p>
</div>
@include('layouts.footer')
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
</body>
</html>
Code language: HTML, XML (xml)
Ok, giờ vào thử http://laravel.dev/register xem thế nào

Nó đã hiện lên rất ok, tiếp theo chúng ta sẽ xử lý phần post dữ liệu form đăng nhập. Chúng ta sẽ tạo thêm một phương thức Laravel Validate để kiểm tra kết quả Google reCAPTCHA trả về, nếu là máy chúng ta sẽ thông báo lên “Form đăng ký không dành cho robot”. Tạo thư mục Validators trong thư mục app và tạo một file ReCaptcha.php với nội dung:
<?php
namespace App\Validators;
use GuzzleHttp\Client;
class ReCaptcha
{
public function validate($attribute, $value, $parameters, $validator){
$client = new Client();
$response = $client->post(
'https://www.google.com/recaptcha/api/siteverify',
['form_params'=>
[
'secret'=>env('GOOGLE_RECAPTCHA_SECRET'),
'response'=>$value
]
]
);
$body = json_decode((string)$response->getBody());
return $body->success;
}
}
Code language: HTML, XML (xml)
Trong class ReCaptcha chúng ta có sử dụng class Client trong gói guzzlehttp/guzzle, thực hiện cài đặt gói này vào project:
c:\xampp\htdocs\laravel-test>composer require guzzlehttp/guzzle
Using version ^6.2 for guzzlehttp/guzzle
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 4 installs, 0 updates, 0 removals
- Installing guzzlehttp/promises (v1.3.1): Loading from cache
- Installing psr/http-message (1.0.1): Loading from cache
- Installing guzzlehttp/psr7 (1.4.2): Downloading (100%)
- Installing guzzlehttp/guzzle (6.2.3): Downloading (100%)
Writing lock file
Generating autoload files
> Illuminate\Foundation\ComposerScripts::postUpdate
> php artisan optimize
Generating optimized class loader
The compiled services file has been removed.
Code language: JavaScript (javascript)
Tiếp theo chúng ta đăng ký validator vừa tạo vào hệ thống để sử dụng, thêm vào phương thức boot() của app\Providers\AppServiceProvider.php:
public function boot()
{
Validator::extend('recaptcha', 'App\Validators\[email protected]');
}
Code language: CSS (css)
Sau đó thêm message lỗi khi kiểm tra reCAPTCHA vào file resources/lang/en/validation.php
'recaptcha'=>'Form đăng ký không dành cho robot'
Code language: PHP (php)
Trong phương thức validator() của RegisterController (app\Http\Controllers\Auth\RegisterController.php) thêm kiểm tra kết quả Google reCAPTCHA:
/**
* Get a validator for an incoming registration request.
*
* @param array $data
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
'g-recaptcha-response'=>'required|recaptcha',
]);
}
Code language: PHP (php)
Ok, vậy là đã tích hợp xong Google reCAPTCHA vào form đăng ký trong Laravel.
Cảm ơn các bạn đã đọc.
Các bạn có thể tham khảo các bài viết hay về Laravel tại đây.
Hãy tham gia nhóm Học lập trình để thảo luận thêm về các vấn đề cùng quan tâm.
Nguồn tham khảo: allaravel
Leave a Reply