如何在Symfony控制器中检查reCAPTCHA的勾选?

nwnhqdif  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(159)

bounty还有2天到期。回答此问题可获得+50声望奖励。Emilie Tossan正在寻找一个答案从一个有信誉的来源:谢谢你帮助我理解这一点。

我想知道是否有可能在控制器php中检查reCAPTCHA的标记。我想这样做,以便我可以作出一个条件,以显示一个错误消息的情况下,用户没有勾选“我不是一个机器人”复选框。
我试着这样做:

  • contact.html.twig* 文件
{% trans_default_domain 'contact' %}

{% extends 'base.html.twig' %}

{% block main %}

{{ form_start(form, {'attr' : {'id' : 'contactform', 'novalidate' : 'novalidate'}} ) }}

{{ form_widget(form.name) }}
{{ form_label(form.name, 'contact.name' | trans ) }}

{{ form_widget(form.email) }}
{{ form_label(form.email, 'contact.email' | trans ) }}

{{ form_widget(form.message) }}
            
{% for message in app.flashes('captcha') %}
    <p class="text-danger">{{ 'contact.error.captcha' | trans }}</p>
{% endfor %}

{{ form_widget(form.save, {'label': 'contact.send' | trans } ) }}

{{ form_end(form) }}

<script>

    function renderReCaptcha(widget) {
        var form = widget.closest('form');
        var widgetType = widget.getAttribute('data-type');
        var widgetParameters = {
            'sitekey': '{{ gg_recaptcha_site_key }}'
        };

        if (widgetType == 'invisible') {
            widgetParameters['callback'] = function () {
                form.submit()
            };
            widgetParameters['size'] = "invisible";
        }

        var widgetId = grecaptcha.render(widget, widgetParameters);

        if (widgetType == 'invisible') {
            bindChallengeToSubmitButtons(form, widgetId);
        }
    }

    function bindChallengeToSubmitButtons(form, reCaptchaId) {
        getSubmitButtons(form).forEach(function (button) {
            button.addEventListener('click', function (e) {
                e.preventDefault();
                grecaptcha.execute(reCaptchaId);
            });
        });
    }

    function getSubmitButtons(form) {
        var buttons = form.querySelectorAll('button, input');
        var submitButtons = [];

        for (var i= 0; i < buttons.length; i++) {
            var button = buttons[i];
            if (button.getAttribute('type') == 'submit') {
                submitButtons.push(button);
            }
        }
        return submitButtons;
    }

</script>

{% endblock %}

字符串

  • ContactController.php* 文件
<?php

namespace App\Controller\Front;

use App\Form\Front\ContactType;
use Symfony\Component\Mime\Email;
use App\Repository\UserRepository;
use App\Form\Front\ContactFromUserType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class ContactController extends AbstractController
{
    #[Route('/contact', name: 'contact')]
    public function contact(
        Request $request, 
        UserRepository $userRepository,
        MailerInterface $mailer): Response
    {
            $form = $this->createForm(ContactType::class);
            $form->handleRequest($request);

            if ($form->isSubmitted() && $form->isValid()) {
                $contactFormData = $form->getData();
                
                if ($contactFormData['captcha'] == []) {
                    $this->addFlash('captcha', 'Si tu n\'es pas un robot, coche la case.');
                } else {
                    $message = (new Email())
                    ->from($contactFormData['email'])
                    ->to('contact@mail.com')
                    ->subject('Message d\'un visiteur !')
                    ->text(
                        '"'.$contactFormData['message'].'"'.\PHP_EOL.\PHP_EOL.
                        $contactFormData['name'].' - '.$contactFormData['email'],
                        'text/plain'
                    );
                    $mailer->send($message);
                }
            }

            return $this->render('front/home/contact.html.twig', [
                'form' => $form->createView()
            ]);
    }
}


我注意到每一个案例$contactFormData['captcha'] == []

  • ReCaptchaValidationListener.php* 文件
<?php

namespace App\Form\EventListener;

use ReCaptcha\ReCaptcha;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\HttpFoundation\Request;

class ReCaptchaValidationListener implements EventSubscriberInterface
{
    private $reCaptcha;

    public function __construct(ReCaptcha $reCaptcha)
    {
        $this->reCaptcha = $reCaptcha;
    }

    public static function getSubscribedEvents()
    {
        return [
            FormEvents::POST_SUBMIT => 'onPostSubmit'
        ];
    }

    public function onPostSubmit(FormEvent $event)
    {
        $request = Request::createFromGlobals();

        $result = $this->reCaptcha
            ->setExpectedHostname($request->getHost())
            ->verify($request->request->get('g-recaptcha-response'), $request->getClientIp());

        if (!$result->isSuccess()) {
            $event->getForm()->addError(new FormError('The captcha is invalid. Please try again.'));
        }
    }
}


是否有解决方案在我的控制器中写入此条件:* 提交表单时是否勾选了reCAPTCHA robot *?

oknwwptz

oknwwptz1#

是的,有一个解决方案可以在控制器中写入此条件。您可以使用g-recaptcha-response请求参数来检查用户是否勾选了reCAPTCHA复选框。如果此参数的值为空,则用户尚未勾选复选框。
下面是如何在控制器中执行此操作的示例:

public function contact(Request $request)
{
    $form = $this->createForm(ContactType::class);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $contactFormData = $form->getData();

        $gRecaptchaResponse = $request->request->get('g-recaptcha-response');

        if (empty($gRecaptchaResponse)) {
            $this->addFlash('captcha', 'If you \'re not a robot, check the box.');
        } else {
            // The user has ticked the reCAPTCHA checkbox.
        }
    }

    return $this->render('front/home/contact.html.twig', [
        'form' => $form->createView()
    ]);
}

字符串

说明:

我们首先检查表格是否已提交且有效。如果是,我们就得到g-recaptcha-response请求参数的值。如果值为空,那么我们知道用户没有勾选reCAPTCHA复选框。然后,我们可以向会话中添加一条flash消息,通知用户他们需要勾选复选框。
如果g-recaptcha-response请求参数的值不为空,那么我们知道用户已经勾选了reCAPTCHA复选框。然后,我们可以在控制器中继续执行任何其他逻辑。

相关问题