Галоўная / Артыкулы

Контроль даступу на адміністрацыю на адміністратыўных ролях у Express з JWT і двума мідлвэрамі

Дазвольце даклэ научыцца, як забезпечыць доступ на адміністрацыйскай пазе Express API за дапамою проміжнага програмнага забезпечэння для аутантыкацыі JWT у поўнасою з абаротным функцыяй authorize(), і калі трэба вярнуць код 401, а калі — 403.

Выдавец: REACTAPP.TOP4 хв чытання1024 слоў

Крыніцы: 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 вытыкаюцца з прызначанай ролі аберанты.
  • Як гэта рэалізуецца ў Express? Адны мідлвэр пераканальвае JWT, другі пераглядае ролю па спісе дазволеных маршрутаў.
  • Дзе трэба гэта застосавіць? У бэкендзе. Прыховыванне кнопак у інтэрфейсе є толькі дэзорганізуючым заходам, адтак як кожны можа безпасабліва вызваць API.
  • Чаму мідлвэр? Ён дазволяе павтарна выкарыстоўваць механізмы автарызацыі і выкалічвае іх з логіки бізнесу, тады адны захід захоўвае многа маршрутаў.
  • Што не пакрывае RBAC? Правіла прыналежнасці, такія як „выкарбкованнікі могу рэдагаваць толькі свой прафіль“, вымагаюць дадатковай пераканальвы пры самай рэсурсе.
  • Узагальненне

    Цэлы процес є простым:

    Client
      ↓
    JWT
      ↓
    Authentication
      ↓
    Authorization / RBAC
      ↓
    Controller
      ↓
    Database
    

    Параверыце аб’явальніка, прачытайце ролю, парабялейце яе з тым, што дазволяе маршрут, а пасля разрэшыце або адхоўначы. Калі праект расте, разважыце асоціяванне ролей з более дробнымі правамі, такімі як user:create, user:update і user:delete, а таксама пераканальванне прав у маршрутах заместо імен ролей. Тады дадзенне новай ролі значыць толькі выправленне адной асоціяцыі, а не кожнага маршрута.