Контроль даступу на адміністрацыю на адміністратыўных ролях у Express з JWT і двума мідлвэрамі
Дазвольце даклэ научыцца, як забезпечыць доступ на адміністрацыйскай пазе Express API за дапамою проміжнага програмнага забезпечэння для аутантыкацыі JWT у поўнасою з абаротным функцыяй authorize(), і калі трэба вярнуць код 401, а калі — 403.
Крыніцы: What is RBAC in Node.js?
У большынце бэкендаў розным пользователям разрашаецца выкананне розных дзействаў: адміністратар можа выдаліць абліквы, менеджер — іх рэдагаваць, а звычайны пользователя можа толькі чытаць. Распалюванне пераказаў if (user.role === ...) у кантролерах быстра стае неконтрольным і лёгка прыводзіць да памылак. Шэйда глядзіце, як выразыць гэтыя правілы як кантроль даступу на аднойчыні з узгадкай ролі (RBAC) у Express за дапамогою двух маленькіх мідлвэраў, а таксама як выбраць правы код статусу, калі запит адхоўваны.
Тыповая матрыца праваў выглядае так:
Admin → Create, Read, Update, Delete
Manager → Read, Update
User → Read
Як RBAC адпавядае парадку обробкі запытаў
RBAC — это модэль автарызаціі: даступ да канцачнай точкі надаецца або адмовляецца на аднойчыні з узгадкай ролі, прыязначанай вызываючаму. У API Node.js на аднойчыні з JWT элементы высталяюць у фіксаванай парадку:
Login
↓
JWT Token
↓
Authentication Middleware
↓
Check User Role
↓
Authorization Middleware
↓
Controller
У цій частцы даюцься адказы на два окольныя пытанні. Аутентыка визначае, хто ўсё-такі є аб’ектам запыту. Автарызацыя выбірае, што гэты аб’ект можа робіць. Раздзелены ў окремыя мідлвэры кожны з іх робіць простым та практычным для тэставання. Глыбокія аспекты разліку розглянуты ў стацыі пра тое, дзе маюць быць аутентыка та автарызацыя.
Спадзяванне ролей да канцэнтраў
Разглянем стандартны набор маршрутаў для керування пользователямі:
GET /api/users
POST /api/users
PUT /api/users/:id
DELETE /api/users/:id
Бажаная політыка для іх:
Admin → All APIs
Manager → GET, PUT
User → GET only
У замест на перакантрольванне ролі ў кожным контралеры, політыку можна дакладзіць декларатывна да кожнага маршрута.
Уключэнне ролі ў токен
Кожны запис пользователя мае свою роль:
{
name: "Ash",
email: "ash@example.com",
role: "admin"
}
Падчас заходу, роль прадаўаецца ў JWT разам з ідэнтыфікатаром пользователя, тады пазнейшыя запиты можна автарызаваць без пашуку ў базе дадзеных:
const token = jwt.sign(
{
userId: user._id,
role: user.role
},
process.env.JWT_SECRET,
{ expiresIn: "1h" }
);
Компрэс: роль застаецца незменнай у токене пакуль ён не выйдзе з часоў. Якщо адміністратара панізуе, стары токен яшчэ прыбліжна гадзину будзе паказваць admin. Короткі тымчас адказу обмежвае гэты періяд; для чутлівых операцый безпечней зноў прачытаць роль з базы дадзеных.
Автарызація запиту
Першы мідлвэр выкарыстоўвае загаловак Authorization: Bearer <token>, пераканаецца ў падпісе та часоўцы токена, а таксама зберагае расшифраваны пакет дадзеных у req.user. Якшто токен не існуе або є нэвалідным, запит завершаецца з кодам 401:
const authenticate = (req, res, next) => {
const token = req.headers.authorization?.split(" ")[1];
if (!token) {
return res.status(401).json({
message: "Authentication required"
});
}
try {
const decoded = jwt.verify(
token,
process.env.JWT_SECRET
);
req.user = decoded;
next();
} catch (error) {
return res.status(401).json({
message: "Invalid or expired token"
});
}
};
Пасля ўжыцьбы кожны наступны обробнік можа даваць веры req.user. Пры перакананні таксама є правильной практыкай задаць спецыфічныя алгорытмы через опцыю algorithms функціі jwt.verify, а не прыймаць все, што заявляе загалоўкі токена.
Разрэшэнне па ролі
Другі мідлвэр – это фабрыка. Яна берае дазволеныя ролі і вяртае обробнік, який адхоўчае кожага, чыя роль не ў списку, з кодам 403:
const authorize = (...roles) => {
return (req, res, next) => {
if (!roles.includes(req.user.role)) {
return res.status(403).json({
message: "Access denied"
});
}
next();
};
};
Заўважыце, што ён чытае req.user.role, таму яго павінны завжды запускать пасля authenticate; сама по сабе яна б выклікала аднойчыну з-за невызначанага req.user.
Захаванне маршруту тепер – цэла прыемка эўх двух элементаў:
router.delete(
"/users/:id",
authenticate,
authorize("admin"),
deleteUser
);
Толькі адміністратар, які працяўвае пасля аутентыкацыі, можа выканаць deleteUser. Дазволенне калькі роўна значыць толькі перадачу большых аргументаў:
router.put(
"/users/:id",
authenticate,
authorize("admin", "manager"),
updateUser
);
Хутчэй адміністраторы і менеджеры можаць адкорэгаваць данні пользователяў.
Выбор между 401 і 403
Этыя два коды часта плутаюцца, але яны сігналізуюць пра разныя проблемы.
401: аберанты не паверыжаны
Сэрвер не ведае, хто аберае, зазвычай з-за аднаго з наступных:
No token
Invalid token
Expired token
Кліент должен зноў заўважыцца або апавежніць свой токен.
403: аберанты вядомы, але не маюць права
Ідэнтычнасць установлена, але ролі не дае права на доступ:
User role = user
Required role = admin
Прабавы з тымі ж данымі не дапаможуць. Короткая правіла: 401 значыць «мы не ведаем, хто вы»; 403 значыць «мы ведаем, і адказ — няма».
Короткі аптак
- Што такое RBAC? Контроль даступу, пры яком разрэшэнняя API вытыкаюцца з прызначанай ролі аберанты.
Узагальненне
Цэлы процес є простым:
Client
↓
JWT
↓
Authentication
↓
Authorization / RBAC
↓
Controller
↓
Database
Параверыце аб’явальніка, прачытайце ролю, парабялейце яе з тым, што дазволяе маршрут, а пасля разрэшыце або адхоўначы. Калі праект расте, разважыце асоціяванне ролей з более дробнымі правамі, такімі як user:create, user:update і user:delete, а таксама пераканальванне прав у маршрутах заместо імен ролей. Тады дадзенне новай ролі значыць толькі выправленне адной асоціяцыі, а не кожнага маршрута.