Задать вопрос

Как правильно защитить форму от спама?

У меня имеется сайт с формой для связи, где пользователь вводит своё имя, E-Mail и пишет своё сообщение. Далее он должен заполнить капчу (ReCaptcha v2) и отправить запрос.
После заполнения данные из формы подставляются в библиотеку PHPMailer и она отправляет мне это сообщение на E-Mail.

Функция работает, но после популяризации сайта, через форму начал приходить спам (причём через заданный промежуток времени). Как правильно защитить форму от спама и на каком именно уровне? Есть мысли, что необходимо создать проверку отправленных данных через DNS (для того, чтобы перед отправкой формы быть уверенным, что они были отправлены именно из моей формы), или проблема с капчей (что робот может обойти её), или проблема вовсе в уязвимости библиотеки PHPMailer. Пробовал разные версии ReCaptcha (v2 и v3). В статистике Google показывает рейтинг пользователей только 0.7 и 0.9 (то есть довольно высокий.). Я на 100% уверен, в статистике отображаются спамеры, так как несколько дней мониторил статистику Google и отправленные мне сообщения.

HTML-форма отправки:

<form action="newform.php" id="feedBackForm" method="POST">
            <label>
                <input class="form" type="text" pattern="^[a-zA-Z-А-Яа-яЁё\s]+$" name="name" id="name" placeholder="Ваше имя" maxlength="20" required oninvalid="this.setCustomValidity('Введите Ваше имя')" oninput="setCustomValidity('')" />
            </label>
            <label>
                <input class="form" type="email" name="email" placeholder="E-Mail" maxlength="50" required oninvalid="this.setCustomValidity('Введите Ваш E-Mail')" oninput="setCustomValidity('')" />
            </label>
            <label>
                <textarea class="form" name="message" placeholder="Сообщение" cols="30" rows="10" style="height:25vh" maxlength="300" required oninvalid="this.setCustomValidity('Напишите сообщение')" oninput="setCustomValidity('')"></textarea>
            </label>
            <label>
                <input id="check" name="check" type="hidden" value="" />
            </label>

            <div class="g-recaptcha" data-sitekey="KeyReCaptcha"></div>
            <div class="text-danger" id="recaptchaError"></div>

            <button onclick="document.getElementById('check').value = 'bread';">Отправить</button>
        </form>


JavaScript-код ReCaptcha:

<script>
            $(document).ready(function () {

                $("#feedBackForm").on("submit", function (event) {
                    event.preventDefault()

                    let captcha = grecaptcha.getResponse();

                    if (!captcha.length) {
                        $('#recaptchaError').text('* Вы не заполнили капчу!');
                    } else {
                        $('#recaptchaError').text('');

                        let dataForm = $(this).serialize()

                        $.ajax({
                            url: 'newform.php',
                            method: 'post',
                            dataType: 'html',
                            data: dataForm,
                            success: function (data) {
                                grecaptcha.reset();
                            }
                        });
                    }
                })
            })
</script>


Причём есть небольшая проверка на стороне сервера:

if ($_POST['check'] != 'bread')
    exit('Spam detected!');
else {
//Отправка сообщения, если не спам
}


В интернете я не нашёл решения этой проблемы, хотя люди с ней сталкиваются.
  • Вопрос задан
  • 2825 просмотров
Подписаться 7 Средний 7 комментариев
Решения вопроса 1
DanArst
@DanArst Куратор тега HTML
Гриффиндор в моде при любой погоде!
Hidden-инпуты для защиты от спама - это фигня. Больше половины ботов раскусят.
Я на многих сайтах ставлю довольно простую защиту, которая отлично работает.
Добавь в форму какой-нибудь текстовый инпут и скрой его стилями, но НЕ ЮЗАЙ display: none;, visibility:hidden;, opacity:0;, так как многие боты и это раскусят.

Например input с name="copyemail":
<form action="">
	<input type="text" name="copyemail" placeholder="Email для копии">
	<input type="text" name="name" placeholder="Имя">
	<input type="email" name="email">
	<button type="submit">Отправить</button>
</form>

и стили для него:
input[name="copyemail"] {
    display: block;
    width: 2px;
    height: 2px;
    margin-bottom: -2px;
    border: none;
    padding: 0;
    opacity: 0.01;
}


И дальше уже на сервере проверяешь:
if ($_POST['copyemail']) {    
    //Это спам! Делаем вид, что сообщение отправлено.
    die('Ваше сообщение отправлено');
} else {
     //Все норм. Метро Люблино, работаем
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 5
vfreelancer
@vfreelancer
php
а если написать свою капчу (несложную)? вряд ли кто-то будет писать бота именно под ваш сайт. и еще: когда-то делали hidden поле в форме. если оно было заполнено, то спам.
Ответ написан
firedragon
@firedragon
Не джун-мидл-сеньор, а трус-балбес-бывалый.
Хм. Попросите войти через соцсеть. Отсеит практически всех. Даже многих валидных.
Ответ написан
Комментировать
Убрать форму из страницы. Генерировать ее js'ом только когда пользователь ткнул в кнопку.
Ответ написан
Adamos
@Adamos
Вне зависимости от капч и прочих технических средств определения живого пользователя - стоит подумать головой, чем отличается то, что вам реально может написать клиент, от того, что пришлет спам-бот.
Например, если в тексте клиента крайне маловероятен фрагмент "http" - можно обойтись и вовсе без капчи... а боты пусть радостно шлют свой шлак в /dev/null.
Ответ написан
Комментировать
@Fubu_By
Можно воспользоваться сторонними сервисами, которые предоставляют API для распознания спама (типо как у google, kolas.ai), но все что хорошее будет взымать плату
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы