Ответ
Фильтрация (санация) и валидация данных должны происходить на нескольких уровнях для обеспечения безопасности и целостности данных (Defense in Depth).
1. Уровень представления (клиентская сторона):
- HTML5-валидация (
required,type="email",pattern) для улучшения UX. - JavaScript-валидация для мгновенной обратной связи.
- Важно: Это ненадежно, так как легко отключается, и служит только для удобства пользователя.
2. Уровень транспорта (сервер, точка входа): Это ключевой уровень. Входящие данные (HTTP-запросы) должны быть проверены и очищены перед передачей в бизнес-логику.
- Валидация: Проверка формата, обязательности, диапазонов, корректности бизнес-правил.
-
Фильтрация: Очистка от потенциально опасных символов (XSS).
// Пример с использованием Symfony Validator и санитизатора class UserRegistrationData { #[AssertNotBlank] #[AssertEmail] private string $email; #[AssertNotBlank] #[AssertLength(min: 8, max: 50)] #[AssertRegex(pattern: '/^(?=.*[a-z])(?=.*[A-Z])(?=.*d).+$/')] private string $password; } // В контроллере $data = new UserRegistrationData(); $data->email = filter_var($request->get('email'), FILTER_SANITIZE_EMAIL); $data->password = $request->get('password'); // Пароли не санитизируют $errors = $validator->validate($data); if (count($errors) > 0) { ... }
3. Уровень бизнес-логики (доменный слой):
- Инварианты предметной области проверяются внутри сущностей (Entities) или доменных сервисов.
class Order { private function __construct(private float $amount) { if ($amount <= 0) { throw new DomainException('Order amount must be positive.'); } } }
4. Уровень persistence (база данных):
- Использование подготовленных выражений (Prepared Statements) для защиты от SQL-инъекций.
- Ограничения на уровне схемы БД (
NOT NULL,UNIQUE,CHECK).
5. Уровень вывода (View/Template):
- Экранирование (escaping) всех пользовательских данных при выводе в HTML, JSON, XML для защиты от XSS.
// В шаблоне Twig экранирование включено по умолчанию <p>Welcome, {{ user.username }}!</p>
Итог: Валидация и фильтрация — это непрерывный процесс, а не одноразовое действие в контроллере.