Хакеры становятся более организованными, в то время как разработчики делают то же самое.

Мойка кредитных карт! Эти три слова вызывают у меня чувство разочарования, паники и истощения одновременно.

Для тех, кто не в курсе, промывка кредитных карт является мошеннической практикой, когда преступники пытаются отмыть украденную информацию о кредитной карте, используя ее для создания поддельных учетных записей или совершения покупок.

Этот процесс включает в себя получение украденной информации о кредитной карте и ее использование для открытия учетных записей на законных веб-сайтах или совершения несанкционированных покупок.

Обычно микротранзакции (от 2 до 20 долларов США) остаются незамеченными. Затем они продают детали в даркнете как «проверенные» карты, надеясь заработать немалые деньги.

Чтобы избежать обнаружения эмитентами кредитных карт, преступники используют различные методы, такие как изменение платежного адреса, использование прокси-серверов или VPN, и автоматизируют этот процесс с помощью скриптов и ботов.

В этой статье мы поговорим об одном инструменте в вашем наборе инструментов Javascript для реализации во внешнем интерфейсе, называемом устранением дребезга. Это отличный способ ограничить количество раз, когда пользователь отправляет форму.

Как защитить свой сайт с помощью Debounce

Существует целый набор инструментов, которые вы можете использовать для защиты своего веб-сайта, включая reCaptcha, 3D Secure (3DS), ограничение скорости, фильтрацию по странам и блокировку злоумышленников с помощью бан-листов.

Однако в этом руководстве мы рассмотрим, как можно использовать JavaScript для реализации ограничения скорости в формах с помощью таких методов, как устранение дребезга.

Устранение неполадок включает в себя задержку отправки формы до тех пор, пока не пройдет определенное количество времени с момента последней попытки отправки.

Этот метод особенно полезен в ситуациях, когда пользователи могут случайно дважды щелкнуть кнопку отправки или несколько раз нажать клавишу ввода. Но это также полезно, чтобы остановить ботов, атакующих ваш сайт так быстро, и действует как способ замедлить их.

Например, установив время задержки в одну секунду, отправка формы будет разрешена только по прошествии секунды с момента последней попытки отправки.

Однако, если это актуально для вашего варианта использования, вы можете установить его на 2 минуты в зависимости от поведения пользователя, что немного усложнит такие вещи, как спам-формы.

TLDR; Версия

Если вы ищете простое решение.

Вот простой пример того, как реализовать устранение дребезга в форме с помощью JavaScript:

const form = document.querySelector('#myForm');
const submitButton = document.querySelector('#submitButton');
let debounceTimeout;

function debounce(callback, wait) {
  if (debounceTimeout) {
    clearTimeout(debounceTimeout);
  }
  
  debounceTimeout = setTimeout(function() {
    callback();
  }, wait);
}

form.addEventListener('submit', function(e) {
  e.preventDefault();
  
  // Disable the submit button
  submitButton.classList.add('disabled');
  
  // Set a new debounce timeout
  debounce(function() {
    // This code will run once the debounce timeout has passed
    console.log('Form submitted!');
    // ... more code to submit the form or handle the data goes here ...
    
    // Enable the submit button
    submitButton.classList.remove('disabled');
  }, 1000); // Set the debounce timeout to 1 second (1000 milliseconds)
});

В этом примере мы используем функцию setTimeout() для задержки отправки формы на 1 секунду (1000 миллисекунд) после последней попытки отправки.

мы также добавляем CSS-класс disabled к кнопке отправки при отправке формы вместо установки атрибута disabled. Это позволяет нам включать и отключать кнопку с помощью CSS вместо JavaScript, что может быть более эффективным.

Это включает в себя добавление к функции debounce() функции обратного вызова в качестве параметра, которая будет выполняться по истечении времени ожидания устранения дребезга. В этой функции обратного вызова мы удаляем класс CSS disabled из кнопки отправки, чтобы снова включить его.

Наконец, мы используем classList.add() и classList.remove() для добавления и удаления класса CSS disabled из кнопки отправки вместо прямой установки атрибута disabled. Это позволяет нам легко включать и выключать класс, и это более семантично и доступно, чем непосредственное манипулирование атрибутом.

Конечно, это всего лишь базовый пример, так что давайте продолжим и создадим что-нибудь, что даст вам реальный пример для игры.

Создание собственного сценария отката

Сегодня мы собираемся создать этот скрипт доступный для использования здесь

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Debounce Example</title>
    <style>
      form {
        display: flex;
        flex-direction: column;
        align-items: center;
        margin: 50px auto;
        padding: 20px;
        border: 1px solid #ccc;
        border-radius: 10px;
        max-width: 500px;
      }

      label {
        display: block;
        margin-bottom: 10px;
      }

      input {
        padding: 10px;
        margin-bottom: 20px;
        border: 1px solid #ccc;
        border-radius: 5px;
      }

      button {
        padding: 10px 20px;
        background-color: #333;
        color: #fff;
        border: none;
        border-radius: 5px;
      }

      button.disabled {
        opacity: 0.5;
        cursor: not-allowed;
      }
    </style>

<script>
  document.addEventListener('DOMContentLoaded', function() {
    const form = document.querySelector('#myForm');
    const submitButton = document.querySelector('#submitButton');
    let debounceTimeout;

    function debounce(callback, wait) {
      if (debounceTimeout) {
        clearTimeout(debounceTimeout);
      }

      debounceTimeout = setTimeout(function() {
        callback();
      }, wait);
    }

    form.addEventListener('submit', function(e) {
      e.preventDefault();

      // Disable the submit button
      submitButton.classList.add('disabled');

      // Set a new debounce timeout
      debounce(function() {
        // This code will run once the debounce timeout has passed
        console.log('Form submitted!');
        // ... more code to submit the form or handle the data goes here ...

        // Send the form data to the server using AJAX
        const formData = new FormData(form);
        const xhr = new XMLHttpRequest();
        xhr.open('POST', 'submit.php');
        xhr.onreadystatechange = function() {
          if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
            console.log('Form data sent successfully');
          }
        };
        xhr.send(formData);

        // Enable the submit button
        submitButton.classList.remove('disabled');
      }, 1000); // Set the debounce timeout to 1 second (1000 milliseconds)
    });
  });
</script>

  </head>
  <body>
    <form id="myForm">
      <label for="name">Name:</label>
      <input type="text" id="name" name="name">
      
      <label for="email">Email:</label>
      <input type="email" id="email" name="email">
      
      <button type="submit" id="submitButton">Submit</button>
    </form>
  </body>
</html>
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  // Get the form data
  $name = $_POST['name'] ?? '';
  $email = $_POST['email'] ?? '';
  
  // Write the data to a file (overwrite the file each time)
  $filename = 'data.txt';
  $data = "Name: $name\nEmail: $email\n\n";
  file_put_contents($filename, $data);
  
  // Send a response to indicate success
  echo 'Data received and written to file successfully.';
} else {
echo 'Invalid request method.';
}

Шаг 1: HTML

Во-первых, нам нужно создать HTML-структуру формы. Вот код базовой формы с двумя полями ввода и кнопкой отправки:

<form id="myForm">
  <label for="name">Name:</label>
  <input type="text" id="name" name="name">
  
  <label for="email">Email:</label>
  <input type="email" id="email" name="email">
  
  <button type="submit" id="submitButton">Submit</button>
</form>

Шаг 2: JavaScript

Теперь мы можем перейти к JavaScript. Вот краткое объяснение того, что делает каждый фрагмент кода:

  • Мы используем document.querySelector для выбора формы и кнопки отправки по их идентификаторам.
  • Мы объявляем переменную debounceTimeout для отслеживания текущего тайм-аута debounce (если есть).
  • Мы определяем функцию debounce, которая принимает функцию обратного вызова и временной интервал в качестве аргументов. Функция debounce вызовет функцию обратного вызова только после того, как пройдет указанный интервал времени, и отменит все предыдущие тайм-ауты, если установлен новый.
  • Мы добавляем прослушиватель событий в форму, которая прослушивает событие submit.
  • Когда форма отправляется, мы предотвращаем поведение отправки формы по умолчанию с помощью e.preventDefault().
  • Мы отключаем кнопку отправки, добавляя к ней класс disabled.
  • Мы вызываем функцию debounce с функцией обратного вызова, которая обрабатывает отправку формы. Внутри этой функции обратного вызова мы можем выполнять любые необходимые задачи, например отправлять данные формы на сервер с помощью AJAX. По истечении тайм-аута debounce будет выполнена функция обратного вызова.
  • Наконец, мы активируем кнопку отправки, удалив класс disabled.
// Wait for the DOM to load before executing the code inside this function
document.addEventListener('DOMContentLoaded', function() {
  // Get a reference to the form and submit button elements
  const form = document.querySelector('#myForm');
  const submitButton = document.querySelector('#submitButton');

  // Initialize a variable to store the debounce timeout
  let debounceTimeout;

  // Define a function to debounce the given callback function
  function debounce(callback, wait) {
    // If there is a previous debounce timeout, clear it
    if (debounceTimeout) {
      clearTimeout(debounceTimeout);
    }

    // Set a new debounce timeout
    debounceTimeout = setTimeout(function() {
      // This code will run once the debounce timeout has passed
      callback();
    }, wait);
  }

  // Attach an event listener to the form's submit event
  form.addEventListener('submit', function(e) {
    // Prevent the default form submission behavior
    e.preventDefault();

    // Disable the submit button
    submitButton.classList.add('disabled');

    // Set a new debounce timeout
    debounce(function() {
      // This code will run once the debounce timeout has passed
      console.log('Form submitted!');

      // Enable the submit button
      submitButton.classList.remove('disabled');
    }, 1000); // Set the debounce timeout to 1 second (1000 milliseconds)
  });
});

Шаг 3: Стиль

Наконец, мы можем добавить несколько основных стилей, чтобы форма выглядела лучше, и дать нам функцию отключения кнопки. Вот код CSS:

form {
        display: flex;
        flex-direction: column;
        align-items: center;
        margin: 50px auto;
        padding: 20px;
        border: 1px solid #ccc;
        border-radius: 10px;
        max-width: 500px;
      }

      label {
        display: block;
        margin-bottom: 10px;
      }

      input {
        padding: 10px;
        margin-bottom: 20px;
        border: 1px solid #ccc;
        border-radius: 5px;
      }

      button {
        padding: 10px 20px;
        background-color: #333;
        color: #fff;
        border: none;
        border-radius: 5px;
      }

      button.disabled {
        opacity: 0.5;
        cursor: not-allowed;
      }

Шаг 4: Бонус

И если вы хотите, чтобы данные отправлялись куда-то, как я, вы можете сделать то же, что и я, и просто создать текстовый файл, который перезаписывает себя каждый раз при отправке кода.

// Get the form data and send it to the server using AJAX
      const formData = new FormData(form);
      const xhr = new XMLHttpRequest();
      xhr.open('POST', 'submit.php');
      xhr.onreadystatechange = function() {
        if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
          console.log('Form data sent successfully');
        }
      };
      xhr.send(formData);
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  // Get the form data
  $name = $_POST['name'] ?? '';
  $email = $_POST['email'] ?? '';
  
  // Write the data to a file (overwrite the file each time)
  $filename = 'data.txt';
  $data = "Name: $name\nEmail: $email\n\n";
  file_put_contents($filename, $data);
  
  // Send a response to indicate success
  echo 'Data received and written to file successfully.';
} else {
echo 'Invalid request method.';
}

Вот и все. Хорошая работа!

Debounce — это полезный инструмент для предотвращения промывки кредитных карт и других форм мошенничества, и я надеюсь, что это дало вам представление о том, как его использовать.

Однако это не должно быть единственным инструментом, используемым для борьбы с мошенничеством.

Другие инструменты, такие как reCaptcha, 3DS и ограничение скорости, также следует использовать в сочетании с debounce для создания комплексной стратегии предотвращения мошенничества вместе со всем, что вы можете найти.