Webrium
Подписаться

Валидация форм: на клиенте, на сервере или везде

Как сделать валидацию удобной для пользователя и безопасной для системы без лишних ошибок и путаницы

Две части валидации: клиентская для удобства, серверная для безопасности, пересекающие границу системыУдобствоБезопасность

Зачем две проверки: удобство против правды

Валидация на клиенте и на сервере — это не дублирующие друг друга механизмы, а два разных инструмента с разными целями. Клиентская проверка существует ради удобства пользователя: мгновенная обратная связь, сокращение количества запросов к серверу, экономия времени на исправление ошибок. Серверная проверка нужна ради правды: данные, которые попадают в базу, должны быть корректными, даже если запрос отправлен в обход формы.

Эти два подхода не заменяют, а дополняют друг друга. Клиентская проверка может пропустить ошибку — например, если пользователь отключил JavaScript или отправил запрос через консоль. Серверная проверка не должна пропускать ничего: она последняя линия обороны перед сохранением данных.

Когда проверять на клиенте: баланс между отзывчивостью и навязчивостью

Проверка на каждом нажатии клавиши — это перебор. Пользователь ещё не закончил ввод, а поле уже подсвечено красным. Это создаёт ощущение, что система торопит или обвиняет, хотя ошибка ещё не совершена. Правильные моменты для проверки на клиенте:

  1. При уходе из поля (blur). Когда пользователь переключается на следующее поле, это сигнал, что он закончил ввод в текущем. В этот момент можно проверить данные и показать ошибку, если она есть.
  2. При отправке формы (submit). Если пользователь нажал кнопку “Отправить”, а какие-то поля заполнены неверно, нужно показать все ошибки сразу, а не по одной. Это экономит время и нервы.

Такой подход даёт баланс между отзывчивостью и ненавязчивостью. Пользователь получает обратную связь, когда она нужна, но не отвлекается на проверки во время ввода.

Почему браузерная проверка не защищает систему

Браузерные атрибуты вроде required, type="email" или pattern — это подсказки для пользователя, а не защита для системы. Они помогают предотвратить случайные ошибки, но не могут остановить намеренные попытки обойти проверку. Любой запрос можно отправить мимо формы, используя инструменты вроде curl или консоль браузера:

curl -X POST https://example.com/api/submit \
  -H "Content-Type: application/json" \
  -d '{"email": "not-an-email", "password": "123"}'

Браузер не остановит такой запрос, потому что он отправлен напрямую на сервер, в обход формы. Поэтому серверная проверка обязательна: она гарантирует, что данные, которые попадают в систему, соответствуют ожиданиям, даже если клиентская проверка была обойдена.

Одно правило на две стороны: как избежать расхождений

Если на клиенте и сервере действуют разные правила валидации, рано или поздно они разойдутся. Например, клиент проверяет длину пароля в 8 символов, а сервер — в 10. Пользователь вводит 9 символов, клиент пропускает, сервер отказывает. Это создаёт путаницу и разочарование.

Решение — единый источник истины. Это может быть:

  • JSON-схема, которая описывает правила валидации и используется и на клиенте, и на сервере.
  • Набор функций, которые реализуют проверку и вызываются с обеих сторон.
  • Библиотека валидации, которая поддерживает несколько языков и платформ.

Такой подход гарантирует, что правила всегда синхронизированы. Если требования к данным меняются, достаточно обновить их в одном месте.

Сообщения об ошибках: конкретность и расположение

Сообщение “Неверный ввод” — бесполезно. Пользователь не знает, что именно не так и как это исправить. Правильные сообщения об ошибках должны быть:

  1. Конкретными. Вместо “Неверный ввод” — “Пароль должен содержать хотя бы одну цифру”. Пользователь сразу понимает, что нужно исправить.
  2. Рядом с полем. Ошибка должна быть видна рядом с полем, которое её вызвало. Модальные окна или сообщения вверху страницы заставляют пользователя искать, к какому полю относится ошибка.
  3. Без обвинений. Не “Вы ошиблись”, а “Поле заполнено неверно”. Ошибки — это нормально, и сообщения не должны создавать ощущение, что пользователь виноват.

Пример хорошего сообщения:

<label for="password">Пароль</label>
<input type="password" id="password">
<span class="error">Пароль должен содержать хотя бы одну цифру</span>

Доступность: ошибки для всех

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

  1. Связать ошибку с полем. Используйте атрибуты aria-describedby или aria-errormessage, чтобы скринридер знал, к какому полю относится ошибка.
  2. Объявить ошибку. Скринридер должен прочитать сообщение об ошибке сразу после поля, чтобы пользователь знал, что не так.

Пример доступного поля с ошибкой:

<label for="email">Email</label>
<input
  type="email"
  id="email"
  aria-describedby="email-error"
  aria-invalid="true"
>
<span id="email-error" role="alert">Введите корректный адрес почты</span>

Атрибут aria-invalid="true" сообщает скринридеру, что поле содержит ошибку, а role="alert" гарантирует, что сообщение будет прочитано сразу.

Тупик: регулярные выражения для всего

Регулярные выражения кажутся универсальным решением для валидации. Например, для проверки email можно использовать такую регулярку:

/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/

Однако у такого подхода есть серьёзные недостатки:

  1. Сложность. Регулярка для email может не покрыть все случаи. Например, она не пропустит плюсовые адреса (user+tag@example.com), которые используются для фильтрации писем. Или международные домены с символами Unicode.
  2. Производительность. Сложные регулярки могут тормозить браузер, особенно если проверка запускается на каждом нажатии клавиши.
  3. Поддержка. Регулярки трудно читать и изменять. Если правила валидации меняются, придётся переписывать регулярку, что может привести к ошибкам.

Для проверки email лучше использовать встроенные средства браузера (type="email") или библиотеки, которые уже протестированы на всех случаях. Для других полей — простые проверки: длина, наличие цифр, соответствие формату. Регулярки стоит использовать только там, где они действительно необходимы, и только после тщательного тестирования.

Когда проверки недостаточно: дополнительные меры

Есть ситуации, когда валидация на клиенте и сервере — это только первый шаг. Например:

  1. Подтверждение email. Чтобы убедиться, что email действительно существует, нужно отправить письмо с подтверждением. Это нельзя сделать на стороне клиента.
  2. Уникальность данных. Если пароль должен быть уникальным (например, в системе регистрации), потребуется проверка в базе данных. Клиентская проверка не может этого гарантировать.
  3. Сложные бизнес-правила. Например, если пользователь может зарегистрироваться только в определённое время или с определённого IP-адреса, эти проверки можно выполнить только на сервере.

В таких случаях валидация на клиенте и сервере — это только начало. За ними следуют дополнительные проверки, которые обеспечивают безопасность и корректность данных.

Позиция редакции

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

Однако, если ресурсы ограничены, приоритет — серверная проверка. Без неё система уязвима, даже если клиентская проверка идеальна. Серверная проверка — это обязательный минимум, без которого нельзя обойтись.

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

Когда валидация не решает проблему

Есть ситуации, когда валидация не может гарантировать корректность данных. Например:

  1. Человеческий фактор. Пользователь может ввести корректный, но неверный email (например, user@example.com вместо user@gmail.com). Валидация пропустит такой адрес, но он не будет работать.
  2. Изменение требований. Если бизнес-правила меняются, старые данные могут перестать соответствовать новым требованиям. Например, если минимальная длина пароля увеличивается с 8 до 10 символов, старые пароли придётся обновить.
  3. Ошибки в логике. Даже идеальная валидация не защитит от ошибок в бизнес-логике. Например, если система позволяет зарегистрироваться с одним email несколько раз, валидация не поможет.

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

С чем это связано

Метка над заголовком говорит, зачем туда идти: продолжить тему, перейти к практике или увидеть возражение.

На шкале времени жизни экрана величина — момент, когда становятся известны входные данные, — пробивает пороговую линию между сервером и клиентом: если данные изсервер/клиентвремя жизни экрана
Предыстория

Где проходит граница клиент — сервер

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

Стык данных и кода в SQL-запросеВвод как данныеВвод как код
Усиление

SQL-инъекция: как она работает и чем закрывается

Защита от SQL-инъекций — критичный слой валидации, который не заменит клиентские проверки, но спасёт данные там, где они уязвимы.

Цепочка шагов аудита доступности: автоматические проверки разметки лежат внутри границы, а последний шаг — поведение по Tab с реальными барьерами — выходит за евидит автоматбарьер в поведении
Практика

Доступность как инженерная задача, а не как галочка

Доступность — это не чек-листы, а работа с поведением интерфейса: как найти барьеры без скринридеров и исправить их на уровне кода, тестов и CSS.

Письмо по вторникам

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

Начните вводить — материалы появятся здесь.

выбрать · Enter открыть · Esc закрыть