Какие существуют уровни валидации данных в веб-приложении

Ответ

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

1. Клиентский уровень (Frontend)

Проверка данных происходит в браузере пользователя до отправки на сервер.

  • Цель: Улучшить UX, предоставив мгновенную обратную связь (например, поле email заполнено неверно).
  • Технологии: Атрибуты HTML5 (required, pattern), JavaScript.
  • Важно: Этот уровень легко обойти, поэтому он никогда не должен быть единственным.
<form>
  <input type="email" name="email" required>
  <input type="number" name="age" min="18">
</form>

2. Серверный уровень (Backend)

Это основной и обязательный уровень валидации. Проверка происходит после получения данных от клиента.

  • Цель: Обеспечить целостность и безопасность данных, так как эту проверку нельзя обойти.
  • Технологии: Библиотеки вроде Pydantic (Python), Joi (Node.js), встроенные средства фреймворков (Django Forms, DRF Serializers).
# Пример с Pydantic в FastAPI
from pydantic import BaseModel, EmailStr, Field

class UserCreate(BaseModel):
    email: EmailStr
    age: int = Field(gt=18, description="Возраст должен быть больше 18")

3. Уровень бизнес-логики

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

  • Цель: Гарантировать соответствие данных бизнес-требованиям.
  • Примеры: Проверка, что баланс пользователя достаточен для совершения покупки; проверка, что промокод еще действителен.
class OrderService:
    def create_order(self, user: User, order_data: Order):
        if user.balance < order_data.total_price:
            raise ValueError("Недостаточно средств на счете")
        # ... логика создания заказа

4. Уровень базы данных (Database)

Последний рубеж защиты целостности данных, реализованный на уровне СУБД.

  • Цель: Предотвратить запись некорректных данных даже в обход логики приложения.
  • Технологии: Ограничения (constraints) UNIQUE, NOT NULL, CHECK, внешние ключи (FOREIGN KEY).
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    age INTEGER CHECK (age > 0)
);

Ответ 18+ 🔞

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

1. Фронтенд, он же "для красоты и скорости"

Тут всё происходит прямо в браузере у юзера. Заполнил почту как попало — тут же ему красненьким подчеркнуло. Цель — чтобы не ждал, пока на сервер улетит и обратно ошибка прилетит. Но это, ёпта, как замок из песка. Ребёнок обойдёт, собака пробежит — и нет замка. Никогда, слышишь, НИКОГДА на него одного не рассчитывай. Это просто вежливость.

<form>
  <input type="email" name="email" required>
  <input type="number" name="age" min="18">
</form>

2. Бэкенд, он же "главный заслон"

А вот это уже, сука, серьёзно. Данные приплыли к тебе на сервер — тут их и надо проверять так, будто от этого зависит твоя жизнь. Потому что от этого и зависит жизнь твоего приложения. Любой распиздяй может отключить JS и слать тебе что угодно. Этот уровень обойти — нихуя не выйдет. Основа основ.

# Пример с Pydantic в FastAPI
from pydantic import BaseModel, EmailStr, Field

class UserCreate(BaseModel):
    email: EmailStr
    age: int = Field(gt=18, description="Возраст должен быть больше 18")

3. Бизнес-логика, он же "а по правилам-то можно?"

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

class OrderService:
    def create_order(self, user: User, order_data: Order):
        if user.balance < order_data.total_price:
            raise ValueError("Недостаточно средств на счете")
        # ... логика создания заказа

4. База данных, он же "последний оплот"

Представь, что все предыдущие уровни — твои охранники. А база данных — это, блядь, бетонный бункер с титановой дверью. Даже если все охранники уснули, проспали и обосрались, дверь должна держаться. UNIQUE, NOT NULL, CHECK — это такие засовы и запоры. На случай, если в логике приложения где-то затесался баг, и какая-то хуйня всё-таки попытается записаться.

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    age INTEGER CHECK (age > 0)
);

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