Валидация на стороне клиента и сервера

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

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

Ключевой принцип проектирования: маска — это помощь пользователю, валидация — это гарантия системы


Ограничения клиентской маски

Использование Inputmask позволяет задать формат поля, например телефон, дату или индекс:

Inputmask("+7 (999) 999-99-99").mask("#phone");

Однако важно учитывать фундаментальные ограничения:

  • пользователь может отключить JavaScript;
  • данные могут быть отправлены напрямую через API;
  • DOM-значения могут быть изменены вручную;
  • вредоносные запросы не проходят через UI-слой.

Следовательно, маска не является механизмом защиты данных.


Клиентская валидация как первый слой проверки

Клиентская валидация дополняет маску, но не заменяет её. Она может использоваться вместе с Inputmask для контроля состояния поля.

Типичные сценарии:

  • проверка заполненности обязательных полей;
  • контроль длины значения;
  • проверка диапазонов (например, возраст);
  • сопоставление с регулярными выражениями.

Пример комбинирования маски и проверки:

const phoneInput = document.querySelector("#phone");

Inputmask("+7 (999) 999-99-99").mask(phoneInput);

phoneInput.addEventListener("blur", () => {
  const value = phoneInput.value;

  const isValid = /^\+7 \(\d{3}\) \d{3}-\d{2}-\d{2}$/.test(value);

  if (!isValid) {
    phoneInput.setCustomValidity("Неверный формат телефона");
  } else {
    phoneInput.setCustomValidity("");
  }
});

Здесь маска формирует структуру ввода, а регулярное выражение проверяет итоговую строку.


HTML5-валидация и Inputmask

Современные браузеры предоставляют встроенные механизмы проверки:

  • required
  • pattern
  • minlength / maxlength
  • type="email", type="number"

Inputmask может работать поверх HTML5-атрибутов, не конфликтуя с ними.

Пример:

<input
  id="email"
  type="email"
  required
  pattern="^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$"
/>
Inputmask({
  alias: "email"
}).mask("#email");

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


Синхронизация маски и бизнес-валидации

Основная проблема при совместном использовании масок и логики проверки — рассинхронизация правил.

Если формат изменяется в Inputmask, а серверная валидация остаётся прежней, возникают ошибки:

  • ложные отклонения корректных данных;
  • принятие некорректных значений;
  • несовместимость API и UI.

Рекомендуемый подход — единый источник правил форматирования:

const phoneMask = "+7 (999) 999-99-99";

Inputmask(phoneMask).mask("#phone");

И зеркальная проверка на сервере:

const phoneRegex = /^\+7 \(\d{3}\) \d{3}-\d{2}-\d{2}$/;

Нормализация данных перед отправкой

Маска влияет только на отображение. Перед отправкой данные должны быть приведены к каноническому виду.

const rawValue = phoneInput.value;

const normalized = rawValue.replace(/\D/g, "");

Такой подход особенно важен, если Inputmask добавляет визуальные символы (+, пробелы, скобки, дефисы).

Часто используется стратегия:

  • UI слой — форматированный ввод;
  • транспортный слой — нормализованные данные;
  • сервер — строгая проверка.

Серверная валидация как обязательный уровень защиты

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

Серверная валидация включает:

  • проверку структуры данных;
  • проверку типов;
  • бизнес-правила;
  • защиту от инъекций;
  • контроль диапазонов значений.

Пример на Node.js:

function validatePhone(phone) {
  const regex = /^\+7\d{10}$/;
  return regex.test(phone);
}

Важно, что сервер не должен полагаться на формат, созданный Inputmask, так как клиент может отправить данные без маски.


Защита от обхода маски

Маска может быть полностью обойдена через:

  • Postman;
  • curl-запросы;
  • изменённый JavaScript;
  • прокси;
  • прямые вызовы API.

Поэтому сервер обязан нормализовать вход:

function sanitize(input) {
  return String(input).replace(/[^\d+]/g, "");
}

Далее уже применяется строгая проверка.


Двойная валидация как стандарт архитектуры

Комбинация клиентской и серверной проверки обеспечивает баланс UX и безопасности:

  1. Inputmask формирует корректный ввод;
  2. клиентская логика предупреждает пользователя;
  3. сервер выполняет окончательную проверку;
  4. данные нормализуются перед сохранением.

Ошибки при проектировании систем с масками

На практике часто встречаются следующие проблемы:

Полное доверие клиенту

Сервер принимает данные без повторной проверки.

Смешивание маски и валидации

Маска начинает выполнять роль бизнес-логики.

Отсутствие нормализации

Сохранение форматированной строки вместо канонического значения.

Несогласованность форматов

Разные правила в UI и backend.

Inputmask должна рассматриваться исключительно как слой представления.


Валидация сложных полей

Для полей с составной структурой (даты, идентификаторы, банковские реквизиты) маска задаёт шаблон, но сервер проверяет:

  • реальность даты (не только формат);
  • контрольные суммы;
  • допустимость диапазонов;
  • соответствие внешним системам.

Пример: дата

Inputmask("99/99/9999").mask("#date");

Серверная проверка:

function isRealDate(str) {
  const [d, m, y] = str.split("/").map(Number);
  const date = new Date(y, m - 1, d);
  return date.getFullYear() === y &&
         date.getMonth() === m - 1 &&
         date.getDate() === d;
}

Безопасность и валидация в контексте масок

Основная угроза — не сам ввод, а последующая интерпретация данных.

Даже если Inputmask гарантирует формат, сервер обязан:

  • экранировать данные при вставке в БД;
  • использовать параметризованные запросы;
  • проверять длину входа;
  • фильтровать управляющие символы.

Итоговая модель обработки данных

Типичный поток данных:

  • ввод пользователя
  • маскирование (Inputmask)
  • клиентская проверка
  • отправка запроса
  • серверная нормализация
  • серверная валидация
  • сохранение

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