Зачем две проверки: удобство против правды
Валидация на клиенте и на сервере — это не дублирующие друг друга механизмы, а два разных инструмента с разными целями. Клиентская проверка существует ради удобства пользователя: мгновенная обратная связь, сокращение количества запросов к серверу, экономия времени на исправление ошибок. Серверная проверка нужна ради правды: данные, которые попадают в базу, должны быть корректными, даже если запрос отправлен в обход формы.
Эти два подхода не заменяют, а дополняют друг друга. Клиентская проверка может пропустить ошибку — например, если пользователь отключил JavaScript или отправил запрос через консоль. Серверная проверка не должна пропускать ничего: она последняя линия обороны перед сохранением данных.
Когда проверять на клиенте: баланс между отзывчивостью и навязчивостью
Проверка на каждом нажатии клавиши — это перебор. Пользователь ещё не закончил ввод, а поле уже подсвечено красным. Это создаёт ощущение, что система торопит или обвиняет, хотя ошибка ещё не совершена. Правильные моменты для проверки на клиенте:
- При уходе из поля (
blur). Когда пользователь переключается на следующее поле, это сигнал, что он закончил ввод в текущем. В этот момент можно проверить данные и показать ошибку, если она есть. - При отправке формы (
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-схема, которая описывает правила валидации и используется и на клиенте, и на сервере.
- Набор функций, которые реализуют проверку и вызываются с обеих сторон.
- Библиотека валидации, которая поддерживает несколько языков и платформ.
Такой подход гарантирует, что правила всегда синхронизированы. Если требования к данным меняются, достаточно обновить их в одном месте.
Сообщения об ошибках: конкретность и расположение
Сообщение “Неверный ввод” — бесполезно. Пользователь не знает, что именно не так и как это исправить. Правильные сообщения об ошибках должны быть:
- Конкретными. Вместо “Неверный ввод” — “Пароль должен содержать хотя бы одну цифру”. Пользователь сразу понимает, что нужно исправить.
- Рядом с полем. Ошибка должна быть видна рядом с полем, которое её вызвало. Модальные окна или сообщения вверху страницы заставляют пользователя искать, к какому полю относится ошибка.
- Без обвинений. Не “Вы ошиблись”, а “Поле заполнено неверно”. Ошибки — это нормально, и сообщения не должны создавать ощущение, что пользователь виноват.
Пример хорошего сообщения:
<label for="password">Пароль</label>
<input type="password" id="password">
<span class="error">Пароль должен содержать хотя бы одну цифру</span>
Доступность: ошибки для всех
Сообщения об ошибках должны быть доступны всем пользователям, включая тех, кто использует скринридеры или другие вспомогательные технологии. Для этого нужно:
- Связать ошибку с полем. Используйте атрибуты
aria-describedbyилиaria-errormessage, чтобы скринридер знал, к какому полю относится ошибка. - Объявить ошибку. Скринридер должен прочитать сообщение об ошибке сразу после поля, чтобы пользователь знал, что не так.
Пример доступного поля с ошибкой:
<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,}$/
Однако у такого подхода есть серьёзные недостатки:
- Сложность. Регулярка для email может не покрыть все случаи. Например, она не пропустит плюсовые адреса (
user+tag@example.com), которые используются для фильтрации писем. Или международные домены с символами Unicode. - Производительность. Сложные регулярки могут тормозить браузер, особенно если проверка запускается на каждом нажатии клавиши.
- Поддержка. Регулярки трудно читать и изменять. Если правила валидации меняются, придётся переписывать регулярку, что может привести к ошибкам.
Для проверки email лучше использовать встроенные средства браузера (type="email") или библиотеки, которые уже протестированы на всех случаях. Для других полей — простые проверки: длина, наличие цифр, соответствие формату. Регулярки стоит использовать только там, где они действительно необходимы, и только после тщательного тестирования.
Когда проверки недостаточно: дополнительные меры
Есть ситуации, когда валидация на клиенте и сервере — это только первый шаг. Например:
- Подтверждение email. Чтобы убедиться, что email действительно существует, нужно отправить письмо с подтверждением. Это нельзя сделать на стороне клиента.
- Уникальность данных. Если пароль должен быть уникальным (например, в системе регистрации), потребуется проверка в базе данных. Клиентская проверка не может этого гарантировать.
- Сложные бизнес-правила. Например, если пользователь может зарегистрироваться только в определённое время или с определённого IP-адреса, эти проверки можно выполнить только на сервере.
В таких случаях валидация на клиенте и сервере — это только начало. За ними следуют дополнительные проверки, которые обеспечивают безопасность и корректность данных.
Позиция редакции
Валидация на клиенте и сервере — это не взаимоисключающие подходы, а дополняющие друг друга механизмы. Клиентская проверка улучшает пользовательский опыт, серверная — защищает систему. Обе нужны, но каждая решает свою задачу.
Однако, если ресурсы ограничены, приоритет — серверная проверка. Без неё система уязвима, даже если клиентская проверка идеальна. Серверная проверка — это обязательный минимум, без которого нельзя обойтись.
Исключение: если данные не критичны (например, форма обратной связи без сохранения в базе), можно ограничиться клиентской проверкой. Но таких случаев мало, и даже в них стоит задуматься о серверной валидации, если данные используются для каких-то решений.
Когда валидация не решает проблему
Есть ситуации, когда валидация не может гарантировать корректность данных. Например:
- Человеческий фактор. Пользователь может ввести корректный, но неверный email (например,
user@example.comвместоuser@gmail.com). Валидация пропустит такой адрес, но он не будет работать. - Изменение требований. Если бизнес-правила меняются, старые данные могут перестать соответствовать новым требованиям. Например, если минимальная длина пароля увеличивается с 8 до 10 символов, старые пароли придётся обновить.
- Ошибки в логике. Даже идеальная валидация не защитит от ошибок в бизнес-логике. Например, если система позволяет зарегистрироваться с одним email несколько раз, валидация не поможет.
В таких случаях валидация — это только первый шаг. За ней должны следовать дополнительные меры: подтверждение email, обновление старых данных, тестирование бизнес-логики. Валидация — это необходимый, но не достаточный инструмент для обеспечения корректности данных.