18 мар. 2025 г.·7 мин чтения

Проверка ввода на клиенте и сервере: что проверяет каждая сторона

Проверка ввода на клиенте и сервере работает лучше всего, когда форма заранее ловит очевидные ошибки, а сервер жёстко применяет правила, защищающие данные.

Проверка ввода на клиенте и сервере: что проверяет каждая сторона

Почему это разделение путает команды

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

Браузер легко вводит в заблуждение. Клиентские проверки формы кажутся надёжными, потому что люди видят, как они работают. Поле краснеет, появляется сообщение, страница сразу реагирует. Такой быстрый отклик хорош для UX, но сам по себе он не создаёт доверия. Это лишь значит, что браузер выполнил какой-то код.

Сервер живёт в другом мире. Он видит итоговый запрос, а не аккуратное поведение формы до отправки. Злоумышленник может вообще пропустить страницу и отправить запросы прямо на сервер, подменив значения, убрав поля или добавив лишние данные, которых форма никогда не показывала. Если команда считает, что проверки в браузере защищают систему, она строит уверенность на том, что пользователи и атакующие могут обойти.

Небольшой пример регистрации показывает, почему всё становится запутанным. Клиент может проверить, что в email есть "@", а длина пароля — не меньше 8 символов. После отправки сервер может отклонить тот же пароль, потому что он слишком распространён, или отклонить email, потому что другой аккаунт уже его использует. С точки зрения пользователя это выглядит как одна система. Внутри продукта это часто две разные кодовые базы, которые меняются в разное время.

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

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

Что клиент должен проверять сразу

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

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

Проверки формата тоже стоит делать на клиенте, если правило однозначное. Поле email может ловить пропущенный символ "@". Поле даты может подсвечивать невозможные даты. Поле телефона может отвергать буквы, если форма ожидает только цифры. Такие проверки не требуют лишнего запроса на сервер.

Ограничения по длине — ещё один простой случай. Если имя пользователя должно быть от 3 до 20 символов, покажите это прямо во время ввода. Небольшой счётчик или короткая подсказка под полем работают лучше, чем если человек напишет 40 символов и провалится позже.

Некоторые варианты становятся недопустимыми из-за предыдущих ответов. Если человек выбирает "бизнес-аккаунт", покажите поля компании. Если он выбирает "частное лицо", скройте их или отметьте как необязательные. Если при выборе страны меняется допустимый формат почтового индекса, сразу обновите это правило на странице. Так вы не даёте выбрать то, что всё равно не сработает.

Текст ошибки должен быть рядом с полем и прямо говорить, что исправить. Лучше короткие сообщения:

  • "Введите email"
  • "Используйте 8 или более символов"
  • "Выберите дату позже сегодняшней"
  • "Номер телефона может содержать только цифры"

Общие сообщения замедляют людей. "Неверный ввод" заставляет их гадать.

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

Что сервер должен всегда контролировать

Всё, что защищает деньги, данные, доступ или хранилище, должно контролироваться на сервере. Браузеры легко подменить. Пользователь может отключить JavaScript, отредактировать запрос или отправить данные через скрипт, а не через вашу форму.

Поэтому серверная проверка — это не запасной вариант. Это финальный рубеж.

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

Правила, связанные с деньгами, тоже остаются на сервере. Если страница оформления заказа показывает сумму $19, сервер должен пересчитать итог по своим данным о товарах, доставке, налогах и скидках. Никогда не доверяйте числу, которое пришло из браузера. То же самое касается купонов, пробных периодов и лимитов тарифов.

Некоторые правила зависят от сохранённых данных, поэтому корректно оценить их может только сервер. Имя пользователя может выглядеть валидным в форме, но сервер знает, занял ли его уже кто-то другой. То же относится к остаткам на складе, инвайт-кодам, слотам бронирования и rate limit. Клиентские проверки формы могут направлять пользователя, но не видят полной картины.

Загрузки файлов тоже требуют жёсткой проверки. Сервер должен проверить реальный тип файла, его размер и любые ограничения по размеру или длине, которые вы задали. Имя файла вроде "photo.jpg" ничего не доказывает. Почти любой файл можно переименовать.

Сервер должен останавливать и небезопасный ввод до того, как он попадёт в хранилище. Задайте чёткие ограничения на длину, допустимые форматы и разрешённые символы там, где это нужно. Если поле допускает 500 символов, сервер должен ограничивать его 500 символами. Если запрос содержит мусор, скрытые управляющие символы или данные, которые не подходят полю, сервер должен отклонить его.

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

Простое правило, чтобы провести границу

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

Такое разделение намного упрощает понимание проверки ввода на клиенте и сервере. Клиент может сказать: "Похоже, email заполнен не полностью" или "Вы пропустили обязательное поле". Сервер должен отвечать на более сложные вопросы: "Этот аккаунт уже существует?" "Может ли этот пользователь менять это поле?" "Разрешена ли эта скидка?"

Быстрый способ провести границу — задать один вопрос: что будет, если кто-то пропустит эту проверку? Люди могут отключить JavaScript, изменить запрос или отправить данные из скрипта вместо вашей формы. Поэтому если пропуск правила может навредить бизнесу, это правило должно быть в серверной проверке.

Обычно клиентские проверки подходят для небольшого набора вещей:

  • обязательные поля
  • базовые проверки формата, например вид email или дата
  • подсказки по длине, например "минимум 8 символов"
  • мгновенная обратная связь, которая помогает исправить ошибки до отправки

Серверные правила покрывают проверки, которым нужен авторитет. Сюда относятся права доступа, уникальность, остатки на складе, статус аккаунта, цены, rate limit и всё, что связано с сохранёнными данными. Форма регистрации — хороший пример. Клиент может предупредить, что пароль слишком короткий. Но сервер всё равно должен отклонить его, если он и правда слишком короткий, уже нарушает политику или указан вместе с email, который уже зарегистрирован.

Некоторые правила должны быть и там, и там. Ограничение длины пароля — частый пример. То же самое касается правила "имя пользователя должно быть от 3 до 20 символов". В таких случаях лучше не вести две немного разные версии вручную, если этого можно избежать. Делитесь определением правил или хотя бы тестами, чтобы обе стороны одинаково принимали и отклоняли одни и те же данные.

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

Как проектировать проверку шаг за шагом

Запланируйте ревью проверок
Подключите внешнюю помощь CTO, пока слабые проверки не превратились в тикеты в поддержку.

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

Удобный способ выстроить проверку ввода на клиенте и сервере — считать клиент быстрым помощником, а сервер — финальным судьёй. Это звучит просто, но работает только если вы выстраиваете правила по порядку.

  1. Сначала перечислите все точки ввода. Учтите веб-форму, мобильное приложение, админку, CSV-импорт, webhook и прямые API-запросы. Если данные могут попасть в систему этим путём, им нужно одинаковое внимание.
  2. Пометьте каждое правило по назначению. Пропущенный "@" в email — это помощь пользователю. Проверка, которая не даёт одному аккаунту редактировать запись другого пользователя, — это безопасность. Ограничения по типу файла или диапазону дат часто относятся к обеим группам.
  3. Напишите сообщения об ошибках до кода проверки. Простой язык делает правила честнее. "Введите email в формате [email protected]" намного лучше, чем "Неверный формат".
  4. Проверьте ошибки в двух направлениях. Сломайте форму в браузере, а потом отправьте плохие запросы прямо в API. Пропускайте поля, добавляйте лишние поля, используйте неверные типы и пробуйте слишком длинные значения.
  5. Логируйте отклонённые запросы с понятной причиной. Со временем начнут видны закономерности. Вы можете обнаружить сломанный мобильный клиент, бота, который бьёт по одному полю, или подпись в форме, которая путает реальных пользователей.

Такой порядок помогает не улететь в теорию. Он ещё и останавливает распространённую проблему: команды строят красивые клиентские проверки формы и считают, что работа закончена. Но скрытое поле, скрипт или прямой запрос могут обойти эти проверки за секунды.

Сообщения об ошибках заслуживают большего внимания, чем им обычно уделяют. Если пользователи пять раз видят "Неверный ввод", они начинают гадать или просто уходят. Если они видят "Пароль должен содержать не менее 12 символов" или "Дата должна быть позже сегодняшней", они быстро исправляют проблему.

С логами тоже важно не переборщить. Записывайте правило, которое не прошло, endpoint и, возможно, имя поля. Не складывайте в логи секреты, полные пароли или платёжные данные.

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

Простой пример регистрации

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

Человек вводит email, пароль и инвайт-код. До нажатия кнопки отправки клиент может проверить, пустые ли поля, похож ли email на email и соответствует ли пароль минимальной длине. Это даёт мгновенную обратную связь и экономит один запрос туда-обратно.

Правило для пароля должно звучать одинаково везде. Если форма говорит "Используйте не менее 12 символов", сервер должен применять ровно такое же правило. Людей раздражает, когда страница говорит одно, а бэкенд молча ждёт чего-то более строгого.

Небольшой поток может выглядеть так:

  • Клиент сразу отмечает пустые поля.
  • Клиент показывает понятную ошибку для email, если формат неверный.
  • Клиент предупреждает, когда пароль слишком короткий.
  • Сервер ещё раз проверяет те же правила после отправки.
  • Затем сервер проверяет то, чему браузер доверять не может.

Именно последняя часть самая важная. Сервер должен решить, используется ли email уже сейчас, настоящий ли инвайт-код, не истёк ли он и не был ли уже использован, а также нужен ли лимит на количество попыток регистрации. Браузер не может безопасно ответить на эти вопросы, потому что любой может обойти клиентские проверки формы.

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

Сообщения об ошибках должны быть короткими и конкретными. Возвращайте одну понятную ошибку на каждую проблему, а затем давайте человеку исправить её и попробовать ещё раз. "Email уже зарегистрирован" лучше, чем расплывчатое "Не удалось создать аккаунт". "Срок действия инвайт-кода истёк" лучше, чем общий код 400.

Если хотите, чтобы форма ощущалась спокойной, держите разделение простым: клиент помогает вводить данные, а сервер принимает окончательное решение.

Ошибки, которые создают ложное чувство надёжности

Усилите проверки на сервере
Перенесите правила для цен, прав доступа и данных туда, где им и место.

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

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

Загрузки файлов создают ту же проблему. Форма, которая проверяет только ".jpg" или ".pdf" в имени файла, по сути лишь создаёт видимость защиты. Переименованный файл может пройти за секунды. Сервер должен проверить реальный тип файла, размер и любые правила по содержимому до того, как что-то сохранит или обработает.

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

Сообщения об ошибках могут делать ситуацию ещё хуже. Если при любом сбое написано "Неверный ввод", пользователи не могут исправить проблему. Они гадают, пробуют снова и раздражаются. Лучшее сообщение говорит, что именно изменить, не раскрывая лишних деталей. "Используйте не менее 12 символов" помогает. "Проверка не пройдена" — нет.

Обычное поведение пользователей ломает многие аккуратные демо:

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

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

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

Короткий чек-лист перед релизом

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

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

  • Оставьте поля пустыми и отправьте форму. Обязательные поля должны остановить ввод заранее в браузере, а сервер всё равно должен отклонить отсутствующие данные, если запрос всё-таки дошёл.
  • Попробуйте слишком длинные или явно некорректные значения. Введите плохой email, буквы в поле телефона или имя, которое выходит за допустимую длину.
  • Обойдите форму в браузере и отправьте запрос напрямую. Если приложение принимает испорченные данные таким способом, значит, правила защиты находятся не там, где нужно.
  • Измените данные, которыми пользователи никогда не должны управлять, например ID, цены, размеры скидок или роли аккаунта. Сервер должен игнорировать или отклонять любые попытки их изменить.
  • Отправьте один и тот же запрос дважды подряд. Проверьте, не создаёт ли приложение дубли заказов, дубли аккаунтов или повторные списания.

Смотрите на текст ошибок не менее внимательно, чем на саму проверку. "Неверный ввод" — это лениво и неудобно. Людям нужно простое сообщение, которое объясняет, что не так и что исправить, например "Пароль должен содержать не менее 12 символов" или "В адресе email не хватает символа @".

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

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

Что делать дальше

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

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

  • Давайте быструю обратную связь на клиенте, когда это помогает людям исправить ввод раньше. Хорошие примеры — пустые обязательные поля, неверный формат email, слабые подсказки по паролю или файл, который явно слишком большой.
  • Все правила доверия держите на сервере. Сюда входят цены, скидки, права доступа, владение аккаунтом, rate limits, проверки остатка и всё, что записывает данные, которым вы должны доверять позже.
  • Если правило живёт на обеих сторонах, сделайте сервер источником истины и держите клиентскую версию небольшой.
  • Пока вы рядом, перепишите расплывчатые сообщения об ошибках. "Неверный ввод" замедляет людей. "Используйте не менее 8 символов" помогает исправить проблему.

Делайте это по одной форме за раз. Небольшой проход по одному потоку лучше, чем грандиозный план, который так и не выйдет в релиз. Если checkout позволяет клиенту считать итоговую сумму, перенесите это правило на сервер уже сегодня. Если инструмент импорта принимает строки без ID, пусть клиент сразу покажет проблему, но сервер должен каждый раз отклонять плохие записи.

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

Если ваша команда быстро двигается и использует AI для разработки, правила проверки могут расходиться между продуктом, фронтендом и бэкендом. В таких случаях помогает короткий внешний разбор. Oleg работает со стартапами и небольшими командами над архитектурой, серверными правилами, инфраструктурой и AI-ориентированными процессами разработки, поэтому профессиональная консультация может выявить слабые места до того, как они превратятся в баги, ошибки в списаниях или обращения в поддержку.