Hier eine Implementierung von Google reCAPTCHA in einer Extbase Extension. Als Beispiel dient ein Anmeldeformular (E-Mail, Captcha). Die reCAPTCHA Response wird im Model als Property gehalten, die Property ist via Annotations mit dem Validator verknüpft. Somit kann die Überprüfung des Captcha im Rahmen der Domain Object Validierung erfolgen.

Beim (bzw. kurz vor) Absenden des Formulars wird die reCAPTCHA Response von Google angefordert und diese die entsprechende (hidden) Property des Formulares geschrieben.

Kleiner Schönheitsfehler: Das Secret ist hier fest im Validator verankert, eleganter wäre eine dynamische Variante über Typoscript o. ä. Gleiches gilt für den Sitekey, welcher hier statisch im FLUIDTEMPLATE enthalten ist.

Classes/Domain/Validator/ReCaptchaValidator.php

<?php

namespace Vendor\Extension\Domain\Validator;

class ReCaptchaValidator extends \TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator {

    /**
     * This validator always needs to be executed even if the given value is empty.
     * See AbstractValidator::validate()
     *
     * @var bool
     */
    protected $acceptsEmptyValues = false;

    /**
     * Checks the google recaptcha response
     *
     * @param mixed $recaptchaResponse The captcha response that should be validated
     * @api
     */
    public function isValid($recaptchaResponse) {

        $json = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret=THE_VERY_SECRET_SECRET&response=' . $recaptchaResponse);
        $data = json_decode($json);
        if (!$data || !$data->success || $data->success != TRUE) {
            $this->addError('Recaptcha', 1712122017);
        }
    }

}

Classes/Domain/Model/Contact.php

<?php

namespace Vendor\Extension\Domain\Model;

class Contact extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {

    /**
     * email
     *
     * @var string
     * @validate NotEmpty, EmailAddress
     */
    protected $email = '';

    /**
     * recaptchaResponse
     *
     * @var string
     * @validate \Vendor\Extension\Domain\Validator\ReCaptcha
     */
    protected $recaptchaResponse = '';

    /**
     * Returns the email
     *
     * @return string $email
     */
    function getEmail() {
        return $this->email;
    }

    /**
     * Sets the email
     *
     * @param string $email
     * @return void
     */
    function setEmail($email) {
        $this->email = $email;
    }

    /**
     * Returns the recaptchaResponse
     *
     * @return string $recaptchaResponse
     */
    function getRecaptchaResponse() {
        return $this->recaptchaResponse;
    }

    /**
     * Sets the recaptchaResponse
     *
     * @param string $recaptchaResponse
     * @return void
     */
    function setRecaptchaResponse($recaptchaResponse) {
        $this->recaptchaResponse = $recaptchaResponse;
    }

}

Resources/Private/Templates/Contact/New.html

<f:form pluginName="Contact" controller="Contact" action="create" name="newContact" object="{newContact}" enctype="multipart/form-data" id="newContact">

	<!-- email -->
	<label for="email">
		{f:translate(key: 'tx_myext_domain_model_contact.email')}
	</label>
	<f:form.textfield property="email" id="email" class="form-control" errorClass="alert-danger" />

	<!-- captcha -->
	<label for="captcha">
		{f:translate(key: 'text.contact-new.captcha')}
	</label>
	<f:form.validationResults for="newContact.recaptchaResponse">
		<f:if condition="{validationResults.flattenedErrors}">
			<div class="alert alert-danger">
				{f:translate(key: 'validator.recaptcha')}
			</div>
		</f:if>
	</f:form.validationResults>
	<f:form.hidden property="recaptchaResponse" id="recaptchaResponse" />
	<div class="g-recaptcha" data-sitekey="THE_PRIVATE_SITEKEY"></div>

	<!-- submit -->
	<button class="submit recaptcha" type="submit">
		{f:translate(key: 'text.contact-new.submitbutton')}
	</button>

</f:form>

<script src="https://www.google.com/recaptcha/api.js?hl={f:if(condition: '{data.sys_language_uid} == 0', then: 'en', else: 'de')}" async defer></script>

Resources/Public/Js/Script.js

$(document).ready(function () {

    $('.submit.recaptcha').click(function () {
        $('#recaptchaResponse').val(grecaptcha.getResponse());
    });

});




Kommentare