Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

📦 NEW: Honey_Pot pour éviter les robots spameurs #35

Merged
merged 1 commit into from
Aug 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions backend/assets/scss/_user.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,13 @@
align-items: center;
margin-right: 10px; /* Espacement entre les boutons */
}

fieldset.sweet-candy {
opacity: 0;
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
z-index: -1;
}
15 changes: 14 additions & 1 deletion backend/config/packages/monolog.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
monolog:
channels:
- deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists
- honey_pot # Honey pot logs seront loggés dans le fichier de log dédié

when@dev:
monolog:
handlers:
honeypot:
level: info
type: rotating_file
max_files: 10
path: "%kernel.logs_dir%/security/honeypot/honeypot.%kernel.environment%.log"
channels: ["honey_pot"]
main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
channels: ["!event"]
channels: ["!event", "!honey_pot", "!security"]
security:
level: debug
type: rotating_file
max_files: 10
path: "%kernel.logs_dir%/security/auth/security.%kernel.environment%.log"
channels: ["security"]
# uncomment to get logging in your browser
# you may have to allow bigger header sizes in your Web server configuration
#firephp:
Expand Down
61 changes: 61 additions & 0 deletions backend/src/EventSubscriber/Form/HoneyPotSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

declare(strict_types=1);

namespace App\EventSubscriber\Form;

use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;

class HoneyPotSubscriber implements EventSubscriberInterface
{
public function __construct(private LoggerInterface $honeyPotLogger, private readonly RequestStack $requestStack)
{
}

public static function getSubscribedEvents(): array
{
return [
FormEvents::PRE_SUBMIT => 'checkHoneyJar',
];
}

/**
* @description: Vérifie si les champs 'phone' et 'ville' sont remplis, si oui alors c'est un robot dans ce cas on lève une exception pour ne pas traiter le formulaire
*/
public function checkHoneyJar(FormEvent $event): void
{
$request = $this->requestStack->getCurrentRequest();

if (!$request) {
return;
}

// Récupérer les données du formulaire
$data = $event->getData();

// Vérifier si les champs 'ville' et 'phone' sont toujours présent dans les données du formulaire
/* @phpstan-ignore-next-line */
if (!array_key_exists(key: 'phone', array: $data) || !array_key_exists(key: 'ville', array: $data)) {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mettre à jour les noms des champs phone devient "phoneNumberCandy" et ville devient "villeStringCandy"

throw new HttpException(statusCode: Response::HTTP_BAD_REQUEST, message: 'Tu ne peux pas soumettre ce formulaire en ayant supprimé les champs cachés ;-)');
}

// Déstructuring de $data pour récupérer les valeurs de 'phone' et 'ville'
['phone' => $phone, 'ville' => $ville] = $data;
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mettre à jour les noms des champs.


$ip = $request->getClientIp();

// Vérifier si le formulaire a été soumis et s'il est valide
if ('' !== $phone || '' !== $ville) {
$this->honeyPotLogger->info(
message: "Formulaire soumis par un robot. L'adresse IP est : ".$ip." | Le champ phone contient '".$phone."' | Le champ ville contient '".$ville."'",
);
throw new HttpException(statusCode: Response::HTTP_BAD_REQUEST, message: 'Petit robot, tu ne passeras pas !');
}
}
}
8 changes: 6 additions & 2 deletions backend/src/Form/ContactType.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@
namespace App\Form;

use App\Entity\Contact;
use Symfony\Component\Form\AbstractType;
use App\Form\FormExtension\HoneyPotType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class ContactType extends AbstractType
class ContactType extends HoneyPotType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
// On appelle la méthode buildForm() de la classe parente (HoneyPotType) pour ajouter les champs 'phone' et 'ville'
// Cela permet d'éviter la soumission du formulaire par un robot.
parent::buildForm($builder, $options);

$builder
->add(child: 'fullname', type: TextType::class, options: [
'attr' => [
Expand Down
62 changes: 62 additions & 0 deletions backend/src/Form/FormExtension/HoneyPotType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

declare(strict_types=1);

namespace App\Form\FormExtension;

use App\EventSubscriber\Form\HoneyPotSubscriber;
use Psr\Log\LoggerInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\HttpFoundation\RequestStack;

class HoneyPotType extends AbstractType
{
protected const DELICIOUS_HONEY_CANDY_FOR_BOTS = 'phone';
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remplacer le nom du champ en "phoneNumberCandy" pour éviter l'auto-complétion des navigateur (Chrome ou autre lors du pré-remplissage des données dans un formulaire.)

protected const FABULOUS_HONEY_CANDY_FOR_BOTS = 'ville';
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remplacer le nom du champ en "villeStringCandy" pour éviter l'auto-complétion des navigateur (Chrome ou autre lors du pré-remplissage des données dans un formulaire.)


public function __construct(
private readonly LoggerInterface $honeyPotLogger,
private readonly RequestStack $requestStack
) {
}

public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add(
child: self::DELICIOUS_HONEY_CANDY_FOR_BOTS,
type: TextType::class,
options: $this->setHoneyPotFieldsConfiguration()
);

$builder->add(
child: self::FABULOUS_HONEY_CANDY_FOR_BOTS,
type: TextType::class,
options: $this->setHoneyPotFieldsConfiguration()
);

$builder->addEventSubscriber(
subscriber: new HoneyPotSubscriber(
honeyPotLogger: $this->honeyPotLogger,
requestStack: $this->requestStack
)
);
}

/**
* @description: Configuration des champs cachés
* @return array<string, array<string, string>|false>
*/
protected function setHoneyPotFieldsConfiguration(): array
{
return [
'attr' => [
'autocomplete' => 'off',
'tabindex' => '-1',
],
'mapped' => false,
'required' => false,
];
}
}
33 changes: 23 additions & 10 deletions backend/templates/pages/contact/index.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,46 @@
{{ form_start(form, {'attr': {'class': 'row g-4', 'novalidate': ''}}) }}
{% include('partials/_flash-messages.html.twig') %}

<div class="col-sm-6">
<fieldset class="col-sm-6">
{{ form_label(form.fullname, null, {'label_attr': {'class': 'form-label fs-base w-100'}}) }}
{{ form_widget(form.fullname, {'attr': {'class': 'form-control form-control-lg'}}) }}
{{ form_errors(form.fullname) }}
</div>
</fieldset>

<div class="col-sm-6">
<fieldset class="col-sm-6">
{{ form_label(form.email, null, {'label_attr': {'class': 'form-label fs-base w-100'}}) }}
{{ form_widget(form.email, {'attr': {'class': 'form-control form-control-lg'}}) }}
{{ form_errors(form.email, {'attr': {'class': 'invalid-feedback'}}) }}
</div>
</fieldset>

<div class="col-sm-6">
<fieldset class="col-sm-6">
{{ form_label(form.subject, null, {'label_attr': {'class': 'form-label fs-base w-100'}}) }}
{{ form_widget(form.subject, {'attr': {'class': 'form-control form-control-lg'}}) }}
{{ form_errors(form.subject, {'attr': {'class': 'invalid-feedback'}}) }}
</div>
</fieldset>

<div class="col-sm-12">
<fieldset class="col-sm-12">
{{ form_label(form.message, null, {'label_attr': {'class': 'form-label fs-base w-100'}}) }}
{{ form_widget(form.message, {'attr': {'class': 'form-control form-control-lg'}}) }}
{{ form_errors(form.message, {'attr': {'class': 'invalid-feedback'}}) }}
</div>
</fieldset>

<div class="col-sm-12 pt-2">
{# Les champs avec la classe sweet-candy permettent d"éviter les robots spammeurs #}
<fieldset class="sweet-candy">
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mettre à jour les noms des champs.

{{ form_label(form.phone) }}
{{ form_widget(form.phone) }}
{{ form_errors(form.phone) }}
</fieldset>

<fieldset class="sweet-candy">
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mettre à jour les noms des champs.

{{ form_label(form.ville) }}
{{ form_widget(form.ville) }}
{{ form_errors(form.ville) }}
</fieldset>

<fieldset class="col-sm-12 pt-2">
<button class="btn btn-primary w-100" type="submit">Soumettre ma demande</button>
</div>
</fieldset>
{{ form_end(form) }}
</div>
</div>
Expand Down
Loading