Пошук уроків, статей та іншого контенту
Розгляньте автентифікацію, авторизацію, ролі, дозволи та типові моделі контролю доступу в системах.
У системі потрібно відповісти на два різні запитання:
Хто це? — автентифікація.
Що цій особі дозволено? — авторизація.
Разом ці механізми утворюють контроль доступу до ресурсів і дій системи.
Наприклад, користувач може успішно увійти до інтернет-магазину, але це не означає, що він має право:
переглядати замовлення інших користувачів;
змінювати ціни;
видаляти товари;
керувати обліковими записами.
Успішний вхід підтверджує особу, але не надає всіх можливих прав.
Автентифікація — це перевірка того, ким є користувач, сервіс або інша система.
Типовий процес:
Користувач надсилає ідентифікатор, наприклад email або ім’я користувача.
Користувач надсилає доказ своєї особи, наприклад пароль.
Система перевіряє ці дані.
У разі успіху система створює сесію або видає токен.
Доказ особи може належати до одного або кількох факторів:
Знання — пароль або PIN-код.
Володіння — телефон, апаратний ключ, код із застосунку.
Властивість користувача — біометричні дані, наприклад відбиток пальця.
Автентифікація за кількома факторами називається багатофакторною автентифікацією. Вона складніша для зловмисника, оскільки одного викраденого пароля недостатньо.
Паролі не слід зберігати у базі даних у відкритому вигляді. Якщо базу даних буде викрадено, зловмисник одразу отримає всі паролі.
Замість цього система зберігає результат криптографічного хешування пароля. Під час входу:
користувач надсилає пароль;
система хешує його тим самим алгоритмом;
порівнює результат зі збереженим хешем.
Для паролів використовують спеціалізовані алгоритми, наприклад Argon2, bcrypt або scrypt. Простий SHA-256 без спеціального налаштування не є достатнім способом зберігання паролів.
Авторизація — це перевірка, чи має вже автентифікований суб’єкт право виконати певну дію.
Наприклад:
користувач може переглядати власний профіль;
редактор може змінювати статті;
адміністратор може видаляти користувачів;
звичайний користувач не може змінювати системні налаштування.
Авторизація повинна перевіряти не лише тип дії, а й об’єкт, над яким виконується дія.
Наприклад, право edit_profile може дозволяти редагувати лише власний профіль, але не профіль іншого користувача.
Зручно описувати правило доступу через три складові:
Суб’єкт — хто виконує дію.
Ресурс — над чим виконується дія.
Дія — що саме потрібно зробити.
Наприклад:
Користувач із роллю
editorможе редагувати статтю.
У цьому правилі:
суб’єкт — користувач із роллю editor;
ресурс — стаття;
дія — редагування.
Іноді додають умови:
Користувач може редагувати лише статті, автором яких він є.
Тоді дозвіл залежить не тільки від ролі, а й від конкретного ресурсу.
Дозвіл описує одну конкретну дію, яку можна виконати.
Приклади дозволів:
article:read — читати статті;
article:create — створювати статті;
article:update — редагувати статті;
article:delete — видаляти статті;
user:manage — керувати користувачами.
Назви дозволів краще робити конкретними й однозначними.
Роль — це набір дозволів, об’єднаний під спільною назвою.
Наприклад:
reader може читати статті;
editor може читати, створювати та редагувати статті;
admin має всі дозволи для керування системою.
Один користувач може мати одну або кілька ролей.
const roles = {
reader: [
"article:read"
],
editor: [
"article:read",
"article:create",
"article:update"
],
admin: [
"article:read",
"article:create",
"article:update",
"article:delete",
"user:manage"
]
};
const users = [
{
id: 1,
email: "olena@example.com",
roles: ["editor"]
},
{
id: 2,
email: "admin@example.com",
roles: ["admin"]
}
];
function authenticate(email) {
// Пошук користувача є лише прикладом.
// У реальній системі перед цим потрібно перевірити пароль або токен.
return users.find((user) => user.email === email) ?? null;
}
function getUserPermissions(user) {
const permissions = new Set();
for (const role of user.roles) {
for (const permission of roles[role] ?? []) {
permissions.add(permission);
}
}
return permissions;
}
function authorize(user, requiredPermission) {
if (!user) {
return {
allowed: false,
reason: "Користувач не автентифікований"
};
}
const permissions = getUserPermissions(user);
if (!permissions.has(requiredPermission)) {
return {
allowed: false,
reason: "Недостатньо дозволів"
};
}
return {
allowed: true,
reason: "Доступ дозволено"
};
}
const user = authenticate("olena@example.com");
console.log(authorize(user, "article:update"));
// { allowed: true, reason: "Доступ дозволено" }
console.log(authorize(user, "user:manage"));
// { allowed: false, reason: "Недостатньо дозволів" }У цьому прикладі:
authenticate знаходить користувача, тобто виконує спрощену автентифікацію;
getUserPermissions визначає дозволи користувача за його ролями;
authorize вирішує, чи дозволена конкретна дія.
Реальна автентифікація також має перевіряти пароль, сесію або токен. У прикладі це навмисно спрощено, щоб зосередитися на різниці між автентифікацією та авторизацією.
Role-Based Access Control призначає дозволи ролям, а користувачам — ролі.
Схема виглядає так:
Користувач → Роль → Дозволи
Наприклад:
користувач має роль editor;
роль editor має дозвіл article:update;
користувач може редагувати статті.
Переваги RBAC:
проста для розуміння;
зручна для адміністрування;
добре підходить для систем із чіткими типами користувачів.
Обмеження:
складніше описувати правила, залежні від конкретного ресурсу;
велика кількість винятків може призвести до надмірної кількості ролей.
Attribute-Based Access Control приймає рішення на основі атрибутів суб’єкта, ресурсу та контексту.
Приклади атрибутів:
відділ користувача;
тип документа;
власник ресурсу;
час доби;
мережа, з якої надійшов запит.
Приклад правила:
Користувач може переглядати документ, якщо він працює в тому самому відділі, що й документ.
ABAC гнучкіша за RBAC, але правила складніше проєктувати, тестувати й пояснювати.
Access Control List зберігає дозволи безпосередньо для ресурсу або користувача.
Наприклад, для окремого документа може бути вказано:
Олена — читання та редагування;
Андрій — лише читання;
Марія — доступ заборонено.
ACL зручні, коли доступ часто налаштовується окремо для кожного ресурсу. Водночас великі списки можуть стати складними для підтримки.
Роль сама по собі не завжди достатня.
Наприклад, роль user може дозволяти редагувати профіль, але користувач повинен редагувати лише власний профіль. Потрібна додаткова перевірка:
function canEditProfile(user, profile) {
if (!user) {
return false;
}
const isAdministrator = user.roles.includes("admin");
const isOwner = user.id === profile.userId;
// Адміністратор може редагувати будь-який профіль,
// а звичайний користувач — лише власний.
return isAdministrator || isOwner;
}
const currentUser = {
id: 1,
roles: ["editor"]
};
const profile = {
userId: 2,
displayName: "Andrii"
};
console.log(canEditProfile(currentUser, profile));
// falseТакі перевірки називають перевірками власника або перевірками на рівні об’єкта.
У типовому запиті до сервера процес може виглядати так:
Клієнт надсилає облікові дані під час входу.
Сервер перевіряє їх.
Сервер створює сесію або видає токен.
Клієнт надсилає сесію або токен у наступних запитах.
Сервер визначає користувача за сесією або токеном.
Сервер перевіряє дозвіл на конкретну дію.
Сервер або виконує дію, або відмовляє в доступі.
Важливо виконувати авторизацію на сервері. Перевірка кнопок або сторінок лише у клієнтському інтерфейсі не захищає API: зловмисник може надіслати запит безпосередньо.
Для API зазвичай розрізняють дві ситуації:
401 Unauthorized — користувач не автентифікований або облікові дані недійсні.
403 Forbidden — користувач автентифікований, але не має потрібного дозволу.
Наприклад:
запит без сесії — 401;
редактор намагається видалити користувача — 403.
Назви кодів можуть здаватися неочевидними, але саме так вони зазвичай використовуються в HTTP API.
Принцип найменших привілеїв означає, що користувач, сервіс або програма повинні отримувати лише ті права, які необхідні для роботи.
Наприклад:
читачу не потрібен дозвіл на видалення статей;
сервісу звітів не потрібен доступ на зміну даних;
користувачу не потрібно надавати права адміністратора «про всяк випадок».
Цей принцип зменшує наслідки помилок і компрометації облікового запису.
Безпечний підхід:
Якщо дозвіл не було явно надано, дію потрібно заборонити.
Не варто вважати, що користувач має доступ, якщо для нього не знайдено окреме правило. Також слід обережно працювати з роллю адміністратора: її дозволи мають бути чітко визначені, а не реалізовані через безумовний доступ до всього.
Те, що користувач успішно увійшов, не означає, що він може виконувати будь-яку дію.
Прихована кнопка не є захистом. Кожен важливий endpoint повинен перевіряти дозволи на сервері.
Навіть адміністратор бази даних не повинен бачити паролі користувачів. Зберігайте захищені хеші за допомогою спеціалізованих алгоритмів.
Адміністративні права потрібно надавати лише тим користувачам і сервісам, яким вони справді потрібні.
Роль user може дозволяти змінювати власні дані, але не дані інших користувачів. Перевіряйте власника та інші умови доступу.
Якщо система не знайшла дозвіл, безпечніше відмовити в доступі.
Повідомлення на кшталт «такого email не існує» можуть допомогти зловмиснику визначати зареєстровані облікові записи. Повідомлення про невдалий вхід краще робити загальним.
Автентифікація визначає, хто виконує запит.
Авторизація визначає, що цьому суб’єкту дозволено.
Дозвіл описує конкретну дію над ресурсом.
Роль об’єднує набір дозволів.
RBAC базується на ролях, ABAC — на атрибутах, а ACL — на списках доступу для ресурсів.
Права потрібно перевіряти на сервері та на рівні конкретного ресурсу.
Безпечна система дотримується принципу найменших привілеїв і за замовчуванням забороняє невідомі дії.