JavaScript в браузере исполняется на устройстве пользователя. Любой злоумышленник или тестировщик может:
required через DevTools (F12);curl или Postman.Интерфейс и база данных решают принципиально разные задачи:
input, blur);Ключевое правило безопасности регулярных выражений — строгое ограничение начала и конца строки:
// КАТАСТРОФА: без якорей /^...$/
const weakPattern = /\d{10}/;
weakPattern.test("мусор 1234567890 грязь"); // Вернет TRUE!
// ЭТАЛОН: строгие границы начала (^) и конца ($)
const strictPattern = /^\d{10}$/;
strictPattern.test("1234567890"); // TRUE (строго 10 цифр)
strictPattern.test("мусор 1234567890"); // FALSE (отклонено)
Популярные маски: ИНН юрлица: /^\d{10}$/ | БИК банка: /^04\d{7}$/ | ОГРН: /^\d{13}$/ | Email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
Случайная опечатка в одной цифре ИНН пройдет проверку по количеству знаков ^\d{10}$, но приведет к созданию некорректного контрагента.
10-я цифра ИНН вычисляется математически по весовым коэффициентам: [2, 4, 10, 3, 5, 9, 4, 6, 8].
function checkInn10(inn) {
if (!/^\d{10}$/.test(inn)) return false;
const w = [2, 4, 10, 3, 5, 9, 4, 6, 8];
let sum = 0;
for (let i = 0; i < 9; i++) {
sum += parseInt(inn[i]) * w[i];
}
return (sum % 11) % 10 === parseInt(inn[9]);
}
Что происходит, когда программист соединяет строки запроса через конкатенацию:
// Опасный код бэкенда:
String sql = "SELECT * FROM users WHERE login = '" + req.get("login") + "' AND pass = '" + pass + "'";
// Если злоумышленник введет в поле логина: admin' --
// Запрос превращается в:
SELECT * FROM users WHERE login = 'admin' --' AND pass = '...'
// Символы -- превращают весь остаток запроса в комментарий! Вход без пароля выполнен!
СУБД парсит SQL-текст с плейсхолдерами $1, $2, строит дерево синтаксического разбора (AST) и компилирует план. На этом шаге структура запроса зафиксирована навсегда.
Параметры передаются по бинарному протоколу отдельно. Любые кавычки или спецсимволы обрабатываются ядром как литеральный текст. Внедрить код невозможно математически!
-- Протокол PostgreSQL Prepared Statements:
PREPARE auth_stmt (text, text) AS
SELECT id, full_name FROM users WHERE login = $1 AND pass_hash = $2;
EXECUTE auth_stmt('admin' OR 1=1 --', 'hash123'); -- Ищет буквального юзера с таким именем!
Ограничения в СУБД действуют как последняя линия обороны, которую невозможно обойти:
CREATE TABLE bank_accounts (
account_id BIGSERIAL PRIMARY KEY,
account_number CHAR(20) NOT NULL,
bik CHAR(9) NOT NULL,
current_balance NUMERIC(15,2) NOT NULL DEFAULT 0.00,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
-- Серверные предикаты целостности:
CONSTRAINT chk_account_format CHECK (account_number ~ '^\d{20}$'),
CONSTRAINT chk_bik_format CHECK (bik ~ '^04\d{7}$'),
CONSTRAINT chk_non_negative_balance CHECK (current_balance >= 0.00)
);
check_violation.
Когда условия зависят от данных других таблиц, декларативного CHECK недостаточно:
CREATE OR REPLACE FUNCTION trg_verify_stock() RETURNS TRIGGER AS $$
BEGIN
-- Блокируем складской остаток от конкурентных изменений
IF (SELECT stock_qty FROM products WHERE id = NEW.product_id FOR UPDATE) < NEW.quantity THEN
RAISE EXCEPTION 'Товар отсутствует на складе в требуемом количестве!'
USING ERRCODE = 'check_violation';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER check_stock_before_order
BEFORE INSERT ON order_items
FOR EACH ROW EXECUTE FUNCTION trg_verify_stock();
Пользователь А и Пользователь Б одновременно оформляют последний билет на рейс. Оба видят «свободно 1 место». Без транзакционной защиты оба выполнят вставку, вызвав овербукинг!
Международный стандарт ISO/IEC 9075 кодирует все ошибки СУБД пятизначными шифрами:
23505: unique_violation (дубликат ключа)23514: check_violation (нарушен CHECK)23503: foreign_key_violation (нет родителя)23P01: exclusion_violation (пересечение)40001: serialization_failure (гонка транзакций)40P01: deadlock_detected (взаимная блокировка)P0001: raise_exception (пользовательский триггер)Трансляция технического исключения СУБД в безопасное экранное уведомление:
ERROR: duplicate key value violates
unique constraint "clients_inn_key"
DETAIL: Key (inn)=(7701234567) already exists.
Раскрывает злоумышленнику схему БД, имена полей и таблиц.
switch (err.code) {
case '23505':
return "Организация с данным ИНН уже зарегистрирована в системе.";
case '23P01':
return "Выбранный номер уже занят на эти даты.";
}
Понятно пользователю, не раскрывает технических деталей.
Валидация ИНН (10 цифр + контрольная сумма) и ОГРН. Перехват 23505 duplicate key при повторной регистрации.
Проверка счета/БИК, клиентский запрет отрицательных сумм. Перехват серверной ошибки недостатка средств.
Маски телефона и email. Перехват ошибки триггера P0001 out of stock при параллельной покупке последнего товара.
Клиентский контроль Дата_выезда > Дата_заезда. Перехват 23P01 exclusion_violation наложение интервалов.
^ и $ в регулярных выражениях.FOR UPDATE или EXCLUDE.База данных защищена от повреждения и внедрения вредоносного кода. Пользователи получают быстрый, понятный и отзывчивый интерфейс без зависаний и аварийных сбоев.
Robert'); DROP TABLE Students; --. Когда школа вставила имя ученика через конкатенацию SQL-строки, база данных стерла всех студентов года. Занятие 24 учит будущих разработчиков: использование параметризованных запросов (Prepared Statements) и строгий контроль входных данных в интерфейсе навсегда исключают подобные инциденты!