EMZETT.
Войти

Валидация форм с помощью Zod и схем: безопасная проверка ввода

Коротко: Пользовательскому вводу доверять нельзя; с помощью библиотек схем вроде Zod вы один раз централизованно проверяете форму, тип и границы: в браузере для удобства и на сервере для безопасности.

Подробнее: Всё, что приходит извне (формы, параметры URL, запросы API, cookie), может быть неверным или вредоносным. Валидация гарантирует, что данные соответствуют ожиданиям, прежде чем программа их использует. TypeScript проверяет только на этапе разработки; во время выполнения нужен код проверки.

Подробности

Zod вкратце

import { z } from "zod";
const Signup = z.object({
  email: z.string().email("Invalid email")
  age: z.coerce.number().int().min(13).max(120)
  password: z.string().min(12)
  terms: z.literal("on", { message: "Please agree" })
});
const r = Signup.safeParse(Object.fromEntries(formData));
if (!r.success) return { errors: r.error.flatten().fieldErrors };
const data = r.data; // чисто типизировано

Схема — источник истины: type Signup = z.infer<typeof Signup> создаёт тип TypeScript. Похожие: Valibot, Yup, ArkType, Joi, JSON Schema.

Где проверять?

  • В браузере: быстрая обратная связь (атрибуты HTML required, type=email, pattern, плюс схема). Только удобство, легко обойти.
  • Всегда ещё и на сервере (маршрут API, серверное действие): именно здесь безопасность. Никогда не полагайтесь на то, что браузер проверил.
  • База данных: ограничения (NOT NULL, UNIQUE, CHECK, внешние ключи) как последняя защита.
  • Вывод: экранируйте при отображении (XSS), а не «очищайте и надейтесь».

Хорошие правила

  • Список разрешённого вместо списка запрещённого: допускайте известные хорошие значения (enum, шаблон), а не ищите плохие.
  • Задавайте пределы (длина, размер, количество, диапазон значений), также для загрузки файлов (проверка типа, размера, содержимого).
  • Преобразуйте типы намеренно (coerce), обрезайте пробелы.
  • Сообщения об ошибках полезные, но без внутренних подробностей.
  • Отклоняйте/удаляйте неизвестные поля (предотвращайте массовое присваивание: пользователь не должен суметь отправить isAdmin: true).
  • Кодировка символов и нормализация (адрес почты в нижнем регистре).
  • Ограничение частоты запросов и CAPTCHA/honeypot против спама.

Взаимодействие

С react-hook-form (+ zodResolver) или серверными действиями (useActionState) вы получаете формы с отображением ошибок по полям. Доступность: связывайте ошибки с полем (aria-describedby, aria-invalid), метки, фокус на первом неверном поле. Конфиденциальность: собирайте только необходимые поля. Проверяйте валидацию модульными тестами (верные и неверные примеры, граничные случаи).

См. также: SQL-инъекция, XSS, Ограничение частоты запросов, CAPTCHA, TypeScript