CodeIgniter 4: Как добавить Google reCAPTCHA v3 в CodeIgniter 4
Google reCAPTCHA v3 - это невидимый тип капчи, при котором пользователю не нужно взаимодействовать. Она отслеживает поведение пользователя на сайте и возвращает оценку от 0 до 1 вместе с ответом.
Эта оценка используется для валидации на стороне сервера.
В этом руководстве я покажу, как вы можете добавить Google reCAPTCHA v3 в вашу форму в CodeIgniter 4.
1. Получите ключи Google reCaptcha
Вы можете пропустить этот шаг, если вы уже зарегистрированы в Google reCAPTCHA v3 и у вас есть ключи сайта и секретные ключи.
- Перейдите по следующей ссылке и войдите в свой аккаунт, если вы еще не зарегистрированы.
- Откроется следующая страница.
- Здесь введите label, выберите reCAPTCHA v3 из типа reCAPTCHA, введите имя вашего домена без https, например, makecodes.ru. Вы также можете указать localhost, если хотите проверить его на своей локальной системе.
- Установите флажок Принять условия обслуживания reCAPTCHA и нажмите кнопку Отправить.
- Скопируйте сайт и секретные ключи.
2. Создание переменных в .env
- Откройте файл .env, который находится в корне проекта.
- Здесь определите 2 переменные для хранения капчи сайта и секретных ключей
GOOGLE_RECAPTCHAV3_SITEKEY = 6LdP-nIhAAAAAA6rzq7BTh_jKqIYeKMoaALxkKte
GOOGLE_RECAPTCHAV3_SECRETKEY = 6LdV-nIhAAAAAL-uFI4w9kQUaqMkeU2K3KojlXyE
3. Включите CSRF
- Снова откройте файл .env.
- Удалите # из начала строк security.tokenName, security.headerName, security.cookieName, security.expires и security.regenerate.
- Я обновляю значение security.tokenName на 'csrf_hash_name'. С этим именем считывается CSRF-хэш. Вы можете изменить его на любое другое значение.
- Если вы не хотите перегенерировать CSRF-хэш после каждого запроса, установите security.regenerate = false.
security.tokenName = 'csrf_hash_name'
security.headerName = 'X-CSRF-TOKEN'
security.cookieName = 'csrf_cookie_name'
security.expires = 7200
security.regenerate = true
- Откройте файл app/Config/Filters.php.
- Раскомментируйте 'csrf' в 'before', если он закомментирован.
// Всегда применяется перед каждым запросом
public $globals = [
'before' => [
// 'honeypot',
'csrf',
// 'invalidchars',
],
'after' => [
'toolbar',
// 'honeypot',
// 'secureheaders',
],
];
4. Создание пользовательской проверки для reCaptcha v3
Создайте правило для проверки ответа reCaptcha v3.
- Создайте новый файл CaptchaValidation.php в папке app/Config/.
- Создайте класс CaptchaValidation.
- В классе создайте метод verifyrecaptchaV3(). Здесь имя метода также является именем правила.
- Прочитайте секретный ключ из файла .env и присвойте его $secretkey.
- Отправьте запрос на
https://www.google.com/recaptcha/api/siteverify?secret=".$secretkey."&response=".$str."&remoteip=".$_SERVER['REMOTE_ADDR']
- Здесь нужно передать секретный ключ, ответ recaptcha и IP-адрес.
- Возвращается ответ в формате JSON.
- Если $responseData->success равен true и $responseData->score > 0.6, то возвращается true, в противном случае присваивается сообщение об ошибке в $error и возвращается false.
Вы можете обновить значение $score с 0,6 до любого другого значения. Обязательно установите его в диапазоне от 0,5 до 1.
Готовый код
<?php
namespace Config;
class CaptchaValidation{
public function verifyrecaptchaV3(string $str, ?string &$error = null): bool
{
$secretkey = getenv('GOOGLE_RECAPTCHAV3_SECRETKEY');
if(($str) && !empty($str)) {
$response = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$secretkey."&response=".$str."&remoteip=".$_SERVER['REMOTE_ADDR']);
$responseData = json_decode($response);
$score = 0.6; // 0 - 1
if($responseData->success && $responseData->score > $score) { // Verified
return true;
}
}
$error = "Invalid captacha";
return false;
}
}
Чтобы использовать созданное выше правило валидации, необходимо определить его в файле Validation.php.
- Откройте файл app/Config/Validation.php.
- Включите в него класс Config\CaptchaValidation.
- Укажите CaptchaValidation::class в массиве $ruleSets.
Готовый код
<?php
namespace Config;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Validation\CreditCardRules;
use CodeIgniter\Validation\FileRules;
use CodeIgniter\Validation\FormatRules;
use CodeIgniter\Validation\Rules;
use Config\CaptchaValidation; // Custom reCAPTCHA v3 validation
class Validation extends BaseConfig
{
// --------------------------------------------------------------------
// Setup
// --------------------------------------------------------------------
/**
* Stores the classes that contain the
* rules that are available.
*
* @var string[]
*/
public $ruleSets = [
Rules::class,
FormatRules::class,
FileRules::class,
CreditCardRules::class,
CaptchaValidation::class, // Custom reCAPTCHA v3 validation
];
/**
* Specifies the views that are used to display the
* errors.
*
* @var array<string, string>
*/
public $templates = [
'list' => 'CodeIgniter\Validation\Views\list',
'single' => 'CodeIgniter\Validation\Views\single',
];
// --------------------------------------------------------------------
// Rules
// --------------------------------------------------------------------
}
5. Создание контроллера
Создание контроллера PagesController
php spark make:controller PagesController
Откройте файл app/Controllers/PagesController.php.
Создайте 2 метода:
- index() - Загружает представление индекса.
- submitContactUs() - Этот метод вызывается при отправке формы.
Проверяем отправленные значения. Здесь, для проверки recaptcha, укажите - 'recaptch_response' => 'required|verifyrecaptchaV3',.
verifyrecaptchaV3 - это пользовательское правило валидации, созданное в предыдущем шаге.
Если <form> не прошла валидацию, вернем страницу с сообщением об ошибке, иначе сохраняем сообщение об успехе в SESSION flash и перенаправяем пользователя на route('/').
Готовый код
<?php
namespace App\Controllers;
use App\Controllers\BaseController;
class PagesController extends BaseController
{
public function index(){
return view('index');
}
public function submitContactUs(){
// Validation
$input = $this->validate([
'name' => 'required',
'email' => 'required',
'subject' => 'required',
'message' => 'required',
'recaptcha_response' => 'required|verifyrecaptchaV3',
],[
'recaptcha_response' => [
'required' => 'Please verify captcha',
],
]);
if (!$input) { // Not valid
$data['validation'] = $this->validator;
return redirect()->back()->withInput()->with('validation', $this->validator);
}else{
// Set Session
session()->setFlashdata('message', 'Request Submitted Successfully!');
session()->setFlashdata('alert-class', 'alert-success');
}
return redirect()->route('/');
}
}
6. Маршруты (Routes)
Откройте файл app/Config/Routes.php и создайте 2 маршрута
- /
- page/submitContactUs - Обработка отправки формы.
$routes->get('/', 'PagesController::index');
$routes->post('page/submitContactUs', 'PagesController::submitContactUs');
7. Создание представления
- Создайте файл index.php в папке app/Views/
- Подключите recaptcha js в раздел <head>
<!-- reCAPTCHA JS-->
<script src="https://www.google.com/recaptcha/api.js?render=<?= getenv('GOOGLE_RECAPTCHAV3_SITEKEY') ?>"></script>
Здесь также укажите sitekey.
- Создайте контактную форму и задайте URL действия <?=site_url('page/submitContactUs')?>. Определите событие onsubmit на <form>, которое вызывает onsubmit(event).
- Выведите сообщение об ошибке, если элемент <form> не прошел проверку. В <form> также выведите сообщение об ошибке, если recaptcha не прошла проверку.
- Создайте скрытый элемент #recaptcha_response для хранения ответа токена recapatcha при отправке <form>.
- Создайте кнопку отправки.
Скрипт
- Создайте функцию onsubmit(), которая вызывается при отправке <form>.
- Вызовите grecaptcha.execute на действии submit для получения токена.
- Присвойте токен скрытому элементу #recaptcha_response.
- Отправьте <form>.
Готовый код
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Как добавить Google reCAPTCHA v3 в CodeIgniter 4</title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" >
<!-- reCAPTCHA JS-->
<script src="https://www.google.com/recaptcha/api.js?render=<?= getenv('GOOGLE_RECAPTCHAV3_SITEKEY') ?>"></script>
<!-- Include script -->
<script type="text/jаvascript">
function onsubmit(e) {
e.preventDefault();
grecaptcha.ready(function() {
grecaptcha.execute("<?= getenv('GOOGLE_RECAPTCHAV3_SITEKEY') ?>", {action: 'submit'}).then(function(token) {
// Store recaptcha response
document.getElementById("recaptcha_response").value = token;
// Submit form
document.getElementById("contactForm").submit();
});
});
}
</script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 mt-5" style="margin: 0 auto;">
<?php
// Display Response
if(session()->has('message')){
?>
<div class="alert <?= session()->getFlashdata('alert-class') ?>">
<?= session()->getFlashdata('message') ?>
</div>
<?php
}
?>
<h2 class="mb-4">Contact US</h2>
<?php $validation = \Config\Services::validation(); ?>
<form id="contactForm" method="post" action="<?=site_url('page/submitContactUs')?>" onsubmit="onsubmit(event)">
<?= csrf_field(); ?>
<!-- Recaptcha Error -->
<?php if( $validation->getError('recaptcha_response') ) {?>
<div class="alert alert-danger">
<?= $validation->getError('recaptcha_response'); ?>
</div>
<?php }?>
<div class="form-group mb-4">
<label class="control-label col-sm-2" for="name">Name:</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="name" placeholder="Enter Name" name="name" value="<?= old('name') ?>">
</div>
<!-- Error -->
<?php if( $validation->getError('name') ) {?>
<div class='text-danger mt-2'>
* <?= $validation->getError('name'); ?>
</div>
<?php }?>
</div>
<div class="form-group mb-4">
<label class="control-label col-sm-2" for="email">Email:</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="email" placeholder="Enter Email" name="email" value="<?= old('email') ?>">
</div>
<!-- Error -->
<?php if( $validation->getError('email') ) {?>
<div class='text-danger mt-2'>
* <?= $validation->getError('email'); ?>
</div>
<?php }?>
</div>
<div class="form-group mb-4">
<label class="control-label col-sm-2" for="subject">Subject:</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="subject" placeholder="Enter Subject" name="subject" value="<?= old('subject') ?>" >
</div>
<!-- Error -->
<?php if( $validation->getError('subject') ) {?>
<div class='text-danger mt-2'>
* <?= $validation->getError('subject'); ?>
</div>
<?php }?>
</div>
<div class="form-group mb-4">
<label class="control-label col-sm-2" for="message">Message:</label>
<div class="col-sm-10">
<textarea class="form-control" id="message" name="message"><?= old('message') ?></textarea>
</div>
<!-- Error -->
<?php if( $validation->getError('message') ) {?>
<div class='text-danger mt-2'>
* <?= $validation->getError('message'); ?>
</div>
<?php }?>
</div>
<div class="form-group ">
<div class="col-sm-offset-2 col-sm-10">
<input type="hidden" id="recaptcha_response" name="recaptcha_response" value="">
<button type="submit" class="btn btn-info">Submit</button>
</div>
</div>
</form>
</div>
</div>
</div>
</body>
</html>
Вывод
Используя это, вы можете защитить свой сайт, не заставляя пользователя проверять, кто он - человек или бот.
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.