Ось готовий урок, створений за твоїм майстер-промптом.
🎓 CS50 Style: Захист маршрутів і Permissions
Привіт, друзі! Це CS50 (умовно 😉), і сьогодні ми поговоримо про те, що перетворює ваш веб-додаток із «прохідного двору» на справжню фортецю.
1. 🔥 Вступ: Чому не можна просто «відкрити двері»?
Уявіть, що ви збудували шикарний готель. У вас є номери «Люкс», є кімнати для персоналу, є сейф із грошима. Ви поставили гарні двері, повісили таблички... але забули поставити замки.
Що станеться? Будь-хто з вулиці може зайти в номер «Люкс», поспати там, зайти на кухню, з’їсти стейк, а потім зазирнути в сейф.
Звучить абсурдно, правда? Але саме це відбувається з вашим кодом, коли ви створюєте API або веб-сайт без захисту маршрутів (route protection).
Питання до вас: Якщо ви сховали кнопку "Видалити" на сайті для звичайного користувача, чи означає це, що він не може видалити дані?
Спойлер: Ні. Якщо він знає адресу (URL), він може надіслати туди запит напряму.
Сьогодні ми навчимося бути «вишибалами» (bouncers) вашого коду. Ми розберемося, як сказати: «Ти можеш увійти, а ти — ні».
2. 🧠 Теоретична база: Паспорт і Браслет
У світі безпеки є два поняття, які плутають 90% новачків. Давайте раз і назавжди розберемося.
1. Authentication (Автентифікація) — "Хто ти?"
Це ваш паспорт. Ви вводите логін і пароль, система каже: «О, привіт, Андрію! Я знаю, хто ти».
2. Authorization (Авторизація / Permissions) — "Що тобі можна?"
Це як браслет у готелі "All Inclusive". * Андрій (User) — зелений браслет: може дивитися пости. * Адмін (Admin) — золотий браслет: може видаляти пости і банити Андрія.
Як це працює «під капотом»? (Концепція Middleware)
Уявіть конвеєр на заводі. Ваш запит (Request) їде по стрічці до кінцевої точки (наприклад, видалення посту). Але по дорозі ми ставимо Middleware (проміжний обробник). Це охоронець.
Він бере ваш запит, дивиться на нього і вирішує:
1. Пропустити далі (next()) — якщо у вас є права.
2. Викинути геть (помилка 403 Forbidden) — якщо прав немає.
❗️ Запам'ятайте: Ми ніколи не довіряємо клієнту (браузеру). Ми перевіряємо права ТІЛЬКИ на сервері.
3. 🧪 Приклади: Від швейцара до спецслужб
Примітка: Приклади на JavaScript (Express), але логіка ідентична для Python, PHP чи Java.
Рівень 1: Простий швейцар (IsLoggedIn)
Найпростіший захист. Чи є користувач у системі?
// Middleware: Охоронець на вході
function checkAuth(req, res, next) {
if (req.user) {
// Якщо користувач залогінений — проходь
next();
} else {
// Якщо ні — стій, тобі сюди не можна
res.status(401).send("Спочатку увійдіть у систему!");
}
}
// Використання
app.get('/dashboard', checkAuth, (req, res) => {
res.send("Це секретна панель керування");
});
Питання: Що буде, якщо я спробую зайти на /dashboard без логіна?
Правильно, я отримаю 401 помилку і не побачу контент.
Рівень 2: VIP-зона (Role-Based Access)
Тепер ускладнимо. Залогінені всі, але видаляти товари може тільки Адмін.
function requireAdmin(req, res, next) {
// Спочатку перевіряємо, чи він взагалі залогінений
if (!req.user) return res.status(401).send("Хто ти?");
// Тепер перевіряємо роль
if (req.user.role === 'admin') {
next(); // У тебе золотий браслет, проходь
} else {
res.status(403).send("Вибач, це тільки для адмінів!");
}
}
// Маршрут
app.delete('/delete-product', requireAdmin, (req, res) => {
// Код видалення
res.send("Товар видалено");
});
Питання: Уявіть, що звичайний юзер дуже хитрий і надіслав Postman-запит на /delete-product. Що станеться?
Мідлвар requireAdmin перехопить запит ще ДО того, як спрацює функція видалення, і зупинить його.
Рівень 3: "Це моє!" (Ownership)
Це найтонший момент. Користувач може редагувати свій профіль, але не профіль сусіда. Тут просто ролі 'user' замало.
function isOwner(req, res, next) {
const resourceId = req.params.id; // ID статті, яку хочемо редагувати
const userId = req.user.id; // Мій ID
// У реальності тут запит до БД: "Чий це пост?"
// Уявімо, що ми дізналися: post.authorId === userId
if (post.authorId === userId) {
next();
} else {
res.status(403).send("Це не твоя стаття! Руки геть.");
}
}
4. 🛠 Практична частина
Час закотити рукави! У вас є уявний магазин.
Завдання 1: Фейсконтроль
Напишіть (або опишіть словами) функцію-мідлвар, яка пропускає користувача тільки якщо у нього в профілі є поле isVerified: true. Якщо ні — повертає помилку "Підтвердіть пошту".
Завдання 2: Подвійний агент
Створіть маршрут /secret-files, який доступний ТІЛЬКИ якщо користувач — Адмін АБО Модератор. Звичайним юзерам — зась.
Завдання 3: Виправ помилку новачка Подивіться на цей код і скажіть, чому це дірка в безпеці:
// Frontend (React/Vue/HTML)
if (user.isAdmin) {
showDeleteButton();
}
// Backend
app.delete('/delete-user', (req, res) => {
database.deleteUser(req.body.id);
res.send("Deleted!");
});
(Підказка: Що, якщо я не буду натискати кнопку, а надішлю запит через консоль?)
Завдання 4: Міні-кейс
Ви робите "Netflix". Є фільми безкоштовні, а є за підпискою "Premium".
Як ви організуєте перевірку доступу до фільму за URL /watch/avengers-endgame? Опишіть логіку перевірки.
5. 💡 Мислення як у розробника
Як думає досвідчений сеньйор, коли проектує захист?
1. "Deny by Default" (Заборонено за замовчуванням) Новачок думає: "Що мені треба закрити?" Профі думає: "Я закриваю ВСЕ. А тепер, що мені треба відкрити?" Краще випадково закрити доступ і потім відкрити, ніж випадково залишити відкритим доступ до бази даних клієнтів.
2. Не пиши логіку в контролерах
Не перевіряйте if (user.role === 'admin') всередині кожної функції. Ви забудете це зробити в 10-му файлі. Виносьте це в Middleware (окремий шар захисту).
3. Frontend — це ілюзія
Все, що відбувається у браузері користувача, користувач може змінити. Він може змінити змінну isAdmin = true у консолі браузера. Тому фронтенд ховає кнопки тільки для краси. Реальний захист — тільки на бекенді.
6. 🧩 Підсумок
Отже, що ми маємо сьогодні?
- Автентифікація — це паспорт (вхід).
- Авторизація — це віза або квиток (права).
- Middleware — це ваш надійний охоронець, який стоїть перед кожною важливою дією.
Тепер ви вмієте не просто писати код, який працює, а код, який захищає. Ви більше не будуєте будинки без замків.
Наступного разу: Окей, ми перевіряємо користувача. Але як сервер пам'ятає, що ви залогінилися, коли ви переходите зі сторінки на сторінку? Ми поговоримо про Сесії та JWT токени. Це буде цікаво!
А поки що — це був CS50. Щасти! 👋