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

Безпека API: JWT та OAuth, пераканальванне, обмежэнне колькасці запыткаў, монітарынг.

Практычныя аспекты безпекі API: аутентыкацыя та автарызацыя за дапамою JWT та OAuth, шифраванне, пераканальванне дадзеных, обмежэнне колькасці запыткаў і логаванне, якое фіксуе атакі.

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

Крыніцы: What Are the Best Practices for API Security? A Complete Guide to Securing Modern APIs

Кожны апі-інтерфейс, які вы выкладзеце, ўзьміцца як дзверы да вашай системы, і атакавальнікі пераглядаюць гэтыя дзверы набліжна болей систематычна, чым большасць команд іх тэстуе. Безпека, якая дадаўаецца пасля запуску, часта залишае прасліні: маршрут без захавання, запит, створаны з необработаных дадзеных, тэрмінал заходу, які з радасцю прыймае мільйон спроб. У гэтым кяліку практычна расказана пра стандарты, якія варта знать, пра аблыкі, якія з’являюцца чыста часта, а таксама пра шасць конкрэтных слоёў захавання, якія реалізуюцца ў Node.js з Express, ўпрымкі, каб вы моглі аудытаваць існуючы апі-інтерфейс або стварыць новы з захаванням з самага пачатку.

Спрыйміце тое, што лічыцца далей, як чарт-пераказ, да якога варта вяртацца працаваючы над проектам: перад выпускам, пасля апдэйта, а таксама кожны раз, калі змінююцца залежнасці або маршруты. Рэгулярныя перагляды дапамагаюць выявіць вразламы, калі яны ўсё ўсё маленькія.

Чаму безпека апі-інтерфейса заслуговае на спецыяльную увагу

Саветныя прыемы ўсе больш викорыстоўваюцца для стварэння сучасных продуктав. У змену таму, каб кожную функцыя ствараць самостоятельна, команды інтэгруюць службы платежаў, атрыбутаў, перадачы паведамленняў і обробкі дадзеных чераз чытра апісаныя інтэрфейсы, і ўсё большая колькасць компаній выпускае продукты, якія ў першую чаргу апіруюць на саветныя прыемы. Адна з доследжэнняў рынку ацэнівае рынак саветных прыемаў у 2026 годзе прыблізна у 20 мільярдаў долераў (паўтарэнне звясткі); незалежна ад точнага парадку, залежнасць ад іх існуе і продовжвае растаць.

Гэтае завіснае становішча мае двустороннія наследкі. Саветны прыемы даўаюць законным кліентам готовыя, можна перыякія функцыі, але ў той жытак ствараюць для хакераў добра задокументаваны, прыемны для машын пункт прыходу. Доследжэнняя промыслу рэгулярна выяўляюць, што вялікі частака нарадзекаў адносіцца да саветных прыемаў; у звястцы Traceable за 2023 год 74% нарадзекаў дадзеных апісваецца як наследкі ўжыцця саветных прыемаў.

API-я частаюць знаходзіцца прымо перед самым чутлівым дакументацыяй, якую мае компанія: платформамі ідэнтыфікаціі з персональнымі данымі, фінансавымі записамі, внутрашнімі процесамі. Неавтарызаваны доступ можа прывести да парадкавання дакументацыі, зловжыванняя службамі, фінансавых збыткаў, адніявання доверлівасці кліентаў і штрафаў за законамі пра захаванне дакументацыі. Усёлькія рызыкі такія вялікія, што абавесці безпекі павінны быць частью угод пра рэгламенты аддачы службы нароўна з часам ўработы, і гэтая адпаведальнасць лягае на кожную команду, якая працуе над продуктам, а не толькі на спецыяльную групу з безпекі. Розумным пачаткам яе рэалізацыі є стандарты, якія ўжо былі узгаданыя ў індастрыі.

Стандарты, якія варта знаць, ад OWASP да OAuth і JWT

Стандарты безпекі API — это формальныя спецыфікацыі, пратаколы і рэкамендацыі, якія застаўляюцца на всіх этапах цыклу разработкі програмнага забезпечэння, каб захаванне было адносна стабільным, а не імпровізаваным. Найчастае встрэчаюцыяся з іх:

  • OWASP API Security Top 10: рангаваны список найболей критычных рызыкаў для API, які падтрымвае Open Web Application Security Project. У яму рассматрываюцься такія проблемы, як несправная автарызацыя на рэвэле об’ектаў, падлажванне запытоў з боку сервера і неакранаваная спрацоўка рэсурсаў; гэты список ёсць найлепшым вачэйным пунктом для анаізу апасцярожнасцей.
  • OAuth 2.0 і 2.1: кантэкст автарызацыі на адной стороне. Кліент атрымлівае токен даступу з вызначанымі дыапазонамі прав і выкарыстоўвае яго, каб дзеяць ад імені пользователя, не працуячы з яго паролем; токены абнавлення дазволяюць кліенту атрымліваць новыя токены даступу без падтрымкі пользователя знову.
  • OpenID Connect (OIDC): слой ідэнтыфікацыі, які працуе на базе OAuth. Ён стандартызуе токен ідэнтыфікатора і спосаб яго паўтарной пераканання кліентамі, што дазволяе реалізавацыю елемента адной падпіскі і атрыманне дакумента про профіль ад прадаўцоў ідэнтыфікацыі з можлівасцю взаімадзеяння.
  • JSON Web Tokens (JWTs): кампактны формат токена з сягнункам. На адзінцу з незрозумелым кукіем сесіі, JWT несе свае даны (ID пользователя, ролю, тэрмін дзейна) у самым токене, а сервер перакананае сягнунак, а не шукае інфармацыю пра сесію. Памятайце, што стандартны падпісаны JWT ўкодаваны, а не зашифраваны, таму будзь-хто, у каго ён, можа прачытаць його содержым.
  • Transport Layer Security (TLS): крыптаграфічны пратакол, які лежыць у основе HTTPS. Ён забезпечвае зашыфраванне дадзеных пад час перадачы, аутентыкацыю сторон, якія веду абмен, і перакананню цэліснасці, якое выявляе парадукты.
  • Zero Trust: архітэктурны падход, па якому кожны пользователя і сервіс спрацоўваюць як ненадзеяныя, пакуль не будзе перакананае ўпэўненасць у іх надзеянасці. Ён апыраецца на чыстае перакананае, прынцып мінімальных прав і прыпуск, што нарадзілася якаясь вялікая атака.
  • Рамка кібербезпекі NIST: кераванне, якое добра прыменяецца да архітектуры хмараў і мікросэрвісаў, з акцэнтам на аутентыкацыю, автарызацыю і захаванне дадзейнаў.
  • Прфілі API фінансавага класу (FAPI): падзвышаныя прфілі OAuth і OIDC для сфер з высокым рызыкам, такіх як банківская справа, фінтэх і регулююцыя дадзейны. Яны выклікаюць неабходнасць моцнай аутентыкацыі кліента, стрэльней обработкі запытоў і адпаведзей, а таксама токенаў, якія можна абмежыць па выдавачы, і якія стануць беспараднымі, як толькі будуць крадзеныя, што адмахвае шахрайства і павышае взаімадзейнаемасць.
  • Гэтыя элементы ствараюць моцную базу, аднак яны не ўтвараюць выключныя спісы.

    Аблікаванні, проты якіх вы захоўваецеся

    Уразлівасці, якія найчымчырае з’яўляюцца ў рэальных API, ўключаюць:

    1. Несправна аутантыкацыя: слабыя або вялікія перакананні ў аідэнтыцеце і некальканая обработка сэсій дазволяюць зловерху красты кукі або токены і перадаць іх знову, каб дася даець доступ да вашых служб.
    2. Несправная автарызацыя на рэвэле об’ектаў (BOLA): API перакананае, што корыстнік заўважаны, але не перакананае, што ёму разрашана робіць з конкрэтным записам, таму змена ID у URL адкрывае доступ да дадзэнняў іншай адзобы або да внутраніх процэсаў.
    3. Штыркаванне SQL: данні, кантролюемыя зловерхам, прыўязваюцца да запыту і выкананы базай дадзэнняў. Практычна кожны кліент базай дадзэнняў адказвае механізам параметраў, які безпечна перадае значэнні.
    4. Штыркаванне каманд: недазволеныя данні з запыту доходзяць да шэлу системы або працоўніка каманд, дазволяючы зловерху выканаваць будзь-якія каманды па прывілеях процэса вашаг сервера.
  • Крос-сайт скраптінг (XSS): увядзены скрапт выконваецца ў прыгледачы жертвы ў контэксте вашага прыемлівача, таму зловершальнік можа дзеяць як гэты корыстнік і чытаць даныя, якія зазвычай захіщаецца правілом тэй самай праекцыі.
  • Неправильная налашоўка безпекі: выцеклі ключы API, адкрытыя зменныя сераўіса, праграмаваныя значэнні з занадта шырокімі правамі. Атакаваныя кранталі можна выкарыстоўваць для вызову вашага API або для стварэння рахункоў за платныя сервісы трэціх сторон.
  • Адкрыцье занадта великіх або чулых даных: прыемлівач вяртае цэлы об’ект базы дадзенаў у замене на поля, якія патрэбны кліенту. Нават якщо інтэрфейс ніколі іх не адображае, даныя застаюцца ў кэшах, локальным храненні і вікні сеті прыгледача.
  • Адмова ў аддачы службы (вакол распраўленых атак): наплыв запытоў выкараняе ресурсы сервера або цэлкам выключае API.
  • Залежнасці ад трэціх сторон: ваш API таксама ўжоўцуе іншыя API і пакеты. Кожны з іх расшыроўвае вашу плошчу атакі, і будь-які вылом чы рэзкі зупінкі ў іх становяць вашу проблему.
  • Кожны з гэтых аспектаў мае сваю адпаведную практыку программавання. Рэшта гіду розглядае іх у шасці слоях, выкорыстоўваючы JavaScript і Express у всім.

    1. Аутентыкацыя за дапамогою пароў і JWT: падтверджэнне таго, хто ўваходзіць у сувязь

    Кожны захіщаны API должен заставіць кліента падтвердзіць свою ідэнтычнасць пры выкананні будзь-якіх значаменных дзеянняў, чы то через імя паўнага права і пароль, ключ API чы падписаны токен. Методы аутентыкацыі зазвычай дзеляцца на пяць каляў: аутентыкацыя па імені паўнага права і паролі, багатафакторная аутентыкацыя, аутентыкацыя на аснове токенаў, аутентыкацыя на аснове сертыфікатаў і біометрыя.

    Шырока прычына плутання — гэта, што на самай працо заменяе JWT. Традыцыйныя серверныя сесіі зберагалі стан на сервере і выкарыстоўвалі кукі браузера для перадачы ідэнтыфікатора сесіі. JWT пазбавляе неабходнасці такога пошуку на сервере з кожным запитам, але сама по сабе не пераканальвае достовернасць дакументаў: яшчэ трэба пераканацца ў пароле прынеймна раз перад выдачай токена. Самэльга таму хораша працюе гібрыдная схема. Пользователь заходзіць па адресе электронной пошты і пароле, сервер выдае JWT у разе успеху, а кожны наступны запит прыносіць толькі токен. Перакананне у достовернасці дакументаў і аутентыкацыя з кожным запитам стаюць аднаючымі задачамі, і пароль больш не перадаецца з кожным вызывам.

    У Express бібліятэка Passport падтрымляе обе часты ўжыццём падключаемых стратэгій. Настройка выконваецца за тры крокі.

    Крок 1: зарэўнаваць локальную стратэгію і стратэгію JWT

    Локальная стратэгія выконваліцца адна раз, пад час заходу, і яя адпавядае за пошук пользователя па электроннай паштцы і парабяранне адправленага пароля з зберажаным хэшам. Стратэгія JWT выконваліцца пад кожным захіщаным запытам: яя выявляе токен з загаловка Authorization: Bearer, перакананае падпись па адносу да JWT_SECRET і выявляе пользователя, які адначытаеся ў пэйлоадзе. Экспорт упрыгрупаванага мідлвэра authenticateJWT з параметрам session: false чыніць безстановы характер яго функцыянавання явным.

    const passport = require("passport");
    const LocalStrategy = require("passport-local").Strategy;
    const { Strategy: JwtStrategy, ExtractJwt } = require("passport-jwt");
    
    // Local Strategy: Verify username and password during login.
    passport.use(
      new LocalStrategy(
        { usernameField: "email", passwordField: "password" },
        async (email, password, done) => {
          // Find the user and compare the hashed password.
          // If valid, return the user.
        }
      )
    );
    
    // JWT Strategy: Verify the token on protected requests.
    passport.use(
      new JwtStrategy(
        {
          jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
          secretOrKey: process.env.JWT_SECRET,
        },
        async (payload, done) => {
          // Find the user referenced in the token.
        }
      )
    );
    
    // Middleware
    const authenticateJWT = passport.authenticate("jwt", { session: false, });
    
    module.exports = { passport, authenticateJWT, };
    

    Функцыі паверакання залічваны як каментары тут, і самэ гэта ўсё, што стосуецца рэальнай працы з абараненнем. Для парабелікаў прыменяйце медленны алгорытм хэшавання з салтам, такі як bcrypt або Argon2, і вяртайце адно і тое ж узнакаванне аб бягучасці, незалежна ад таго, чы роўны ўвідны адреса чы ня, чы правільны пароль чы ня, каб канцэнтры не можна было выкарыстоўваць для выявлення, якія абліквоты існуюць.

    Шаг 2: аутентыфікацыя пад час заходжання і падписваўка токена

    Обробнік заходжання запускае локальную стратэгію чераз спецыяльную функцыю-вызов. Адказ пра адказкі пераходзіць у систему карыстоўвання адказак Express, відсутнасць пользователя выдваіць 401, а успешнае парабелікаванне дае токен, падпісаны ID і роллю пользователя, а таксама тэрміном выкарыстоўвання, які бераецца з JWT_EXPIRES_IN, пры чым якщо гэта немагчыма, то выкарыстоўваецца тэрмін у два гадзіны.

    const jwt = require("jsonwebtoken");
    const passport = require("passport");
    
    const login = (req, res, next) => {
      passport.authenticate("local", { session: false }, (err, user, info) => {
        if (err) return next(err);
        if (!user) return res.status(401).json({ message: info.message, });
    
        // Issue a signed JWT after successful authentication.
        const token = jwt.sign(
          { id: user.id, role: user.role,},
          process.env.JWT_SECRET,
          { expiresIn: process.env.JWT_EXPIRES_IN || "2h",}
        );
    
        return res.status(200).json({ message: "Login successful.", token, user,});
      })(req, res, next);
    };
    

    Два моменты заслуговуюць на увагу. Короткі термін дзейнасці вплывае на тое, як давго будзе корыстны вкрадзены токен; якщо сесіі павінны трываць дыяўней, неабходна супараваць короткія токены доступу з процэсам апавяржэння, такім як той, што описаны ў нашай стратэгіі апавяржэння токенам для систем аутэнтыкацыі Node.js. Кроме таго, у адпаведзе вяртаецца user у ўсіх деталях. Якщо гэты об’ект — це сырая рэкорд базы дадзенаў, ён можа міткаваць хэш пароля і внутрэшнія поля, што якраз і є надмерным адкрыццем дадзэнняў, пра якое гаворылася раней. У такім случае трэба вяртаць толькі неабходныя даны, напрыклад ID, адказ на пытанне про электронную пашту і ролю.

    Шаг 3: захаванне захіщаных маршрутаў

    Пасля экспорту мідлвэра захаванне маршрута абыраецца праз размешчэнне функцыі authenticateJWT прынцыпова раней за контролер у вызначэнні маршрута. Запыткі без валіднага токена адхіляюцца ўсё раней, чым запускаецца якая-лібо бізнес-логіка.

    const {  Router } = require("express");
    const authRouter = Router();
    
    // Get auth middleware and sample prorected controller
    const authController = require("../controllers/auth.controller");
    const { authenticateJWT } = require("../middleware/authentication");
    
    // Use JWT as a guard to protect certain routes
    authRouter.get("/me", authenticateJWT, authController.me);
    authRouter.patch("/password", authenticateJWT, authController.updatePassword);
    

    Якщо вы вярбяецеся да лёгкіх рутэраў, той жа захад можа быць уключаны ў сэрберы з’едынення самога кантроллера. У будзьму случае прагніце, каб захаванне было стандартным для рутэра, а публічныя маршруты былі спецыяльна адзначаны як без захавання, замест таго, каб памяцаць прыкладзваць захад кожнаму маршруту окрема.

    2. Автарызацыя і дыяпазоны OAuth: выбір таго, што можа рабіць апылальнік

    Аутентыкацыя адпавядае на запыт «Калі вы?»; автарызацыя — на запыт «Што вам дазволена робіць?». Яна зазвычай выконваліцца ведаў за аутентыкацыяй і пераканае кожную ідэнтычнасць па правілах доступу пры тым, калі надаецца або адмовляецца ў запытэ. Без яе будзь-яны залогаваны корыстнік можа чытаць чутлівыя даны або запускать прывілейованыя дзеянні, і самэ гэта є прычыной вузькіх месцаў BOLA.

    Тры модэлі падпіраюць большасць патрэб:

    • Контроль даступу на адміністратыўнай аснове (RBAC) прызначае правыя на ролі, а ролі — на корыстуначаў. API для блога можа маты ролі адпаведна адміністратара, рэдагувальніка і пераглядача. Бн падходзіць для стабільных функцый і груп, таму ён часта викорыстоўваецца ў корпаратыўных прыкладнах.
    • Контроль даступу на атрыбутнай аснове (ABAC) ацэнюе атрыбуты корыстунача, ресурса і сяродавішча запыту (віддзел, чутлівасць ресурса, час дзяна, сеть) па правілах. Ён падходзіць для API, чыяя рашэнні ў значныяй меры залежнаць ад контексту або часта зміняюцца.
    • Контроль даступу на аснове адносаў (ReBAC) надае даступ на аднойчыну з адносам між корыстуначам і конкрэтным ресурсам, такім як прыналежнасць аб членства ў групе, як правіло, шляхом аналізу графа адносаў. Ён ідеальна падходзіць для саўместных продуктов, такіх як адналежнасць дакументаў аб соцыяльных платформ.

    Самастаяцэнне разрэшэнняў на стварэнне ўсталяванняў — гэта чыраклёвы спосаб разумець ўсе ўсуненасці, але системы вырабніцтва часта перадаюць задачы выдачы та параболікацыі токэнаў адпаведнаму прадаўцу айдэнтыкацыі. Калі API рэгіструецца у такога прадаўца, як Microsoft Entra ID, і налаштаваецца так, каб прымалі токэны-носіцы, чулівыя канцэнтры параболікуюць дыяпазоны та ролі кожнага токэна пры выкананні. Некоректны токэн або відсутнае права прыводзяць да коду 401 Unauthorized. У Express захіщаны маршрут выглядае так:

    app.get(
      "/api/orders",
      passport.authenticate("oauth-bearer", { session: false }),
      (req, res) => {
        res.json({ message: "Protected resource." });
      }
    );
    

    Згадайце, што пасвярджаны токен стварыць можа толькі базовыя правыя на доступ. Пераконтроўкі на рэвэле об’ектаў, такія як «Чы рэчыпак належы гэтаму пользователя?», все рава трэба выканаць у вашам працоўніку або слое дадзэнняў, адтолькі што ніякі прадаўцы аідэнтычнасці не ведае, хто ў вашай базе дадзэнняў ўладае рэчыпакам 4812.

    Што стосуецца самых пратаколаў, паслужыць стандарты індастрыі, такія як OAuth 2.0, OpenID Connect і SAML. Вы можете самі реалізаваць ўсе процесы або перадаць іх прадаўцам аідэнтычнасці, такім як Ping Identity, Okta, Microsoft Entra ID, AWS або IBM Security Verify.

    3. Шифраванне: захаванне дадзэнняў пад час перадачы і у спакоі

    Шифраванне ператварая чытальныя даны на зашыфраваны тэкст, які ўтрачае значэнне без правильнага ключа. TLS заходзіць даны пад час ўсунення іх; шифраванне у стані спакою заходзіць іх там, дзе яны зберагаюцца, укладаючы ў гэта і базу дадзенаў. Чутлівыя системы зазвычай викорыстоўваюць аба спосабы, таму што без шифравання даны, такія як фінансавыя крэдытныя даны, могу быць перехоплены або выкараны з атакаванага сховішча.

    Основныя падходы прыменяюць компроміс между швальнасцю і кантролем ключа:

    • Сіметрычнае шифраванне викорыстоўвае адні раздзялены ключ. Яно дужа швальнае і добра справляецца з вялікімі об’ёмамі дадзенаў, таму яго можна выбраць для шифравання даных у стані спакою і пакетаў дадзенаў, але обе стороны павінны безпечна зберагаць той самы секрэтны ключ.
    • Асіметрычнае шифраванне викорыстоўвае пару публічнага і прыватнага ключа, таму не трэба адмаўляць секрэтны ключ. Яно значна медленнэе і практычнае толькі для маленькіх фрагментаў дадзенаў.
  • Гібрыдная шифрацыя спалюе гэтыя два падходы: асиметрычная крыптаграфія захоўвае сіметрычны ключ, а сіметрычны ключ захоўвае самыя даны. Такім чынам атрыбуты абмяну ключоў ад першага падходу і шырокае выкарыстоўванне даных ад другога падходу стаюць можлівымі.
  • Для сіметрычнай шифрацыі вбудованы модуль crypto у Node падтрымлівае стандарт AES-256-GCM. Наведзены нижэй код серыялізуе тэла запыту, стварае новы вектар ініцыялізацыі дужынай 12 байт, шифруе даны і вяртае вектар ініцыялізацыі, таг аутентыфікацыі GCM і зашифраваны тэкст у виглядзе шэсціканальных страк.

    const crypto = require("crypto");
    
    const algorithm = "aes-256-gcm";
    const key = Buffer.from(process.env.ENCRYPTION_KEY, "hex");
    
    app.post("/api/orders", (req, res) => {
      const iv = crypto.randomBytes(12);
    
      const cipher = crypto.createCipheriv(algorithm, key, iv);
    
      const encrypted = Buffer.concat([
        cipher.update(JSON.stringify(req.body), "utf8"),
        cipher.final(),
      ]);
    
      const payload = {
        iv: iv.toString("hex"),
        tag: cipher.getAuthTag().toString("hex"),
        data: encrypted.toString("hex"),
      };
    
      // Store or transmit the encrypted payload
      res.json(payload);
    });
    

    Калькольныя прычыны робяць гэта правільным. Ключ павінен мячыць роўна 32 байты (64 хэкс-сімвалы ў ENCRYPTION_KEY) і павінен выйшаць з кантролера секрэтных дадзеных, а не з коду выканання. IV павінен быць унікальным для кожнага зашыфравання пад тым самым ключам; павторытакованне IV з GCM мае катастрофічныя наследкі, таму ён генеруецца за кожны запит. Атрыбут аутентыкацыі дапамагае стороне, якая дэзыфруе, выявіць парадукты, таму ён павінен храніцца разам з зашыфраваным тэкстам і пераканальватыцца пад час дэзыфравання. У рэальным сервісе гэты пэйлоад будзе зберагацца або перадаваны далей, а не вяртаны вызывачу, як гэта робіцца ў дэманстрацыі.

    У там самым модуле таксама є асіметрычная зашыфравання. Дадзеныя, зашыфраваныя публічным ключам, можна дэзыфруець толькі за дапамогою адпаведнага прыватнага ключа:

    const crypto = require("crypto");
    
    const encrypted = crypto.publicEncrypt(
      publicKey,
      Buffer.from("Sensitive API data")
    );
    

    Пакалькі RSA можа шифруваць толькі пакет дадзеных, які маюць размер меньшы за размер яе клячы, таму publicEncrypt падходзіць для короткіх значэнняў, такіх як поле з секрэтным дадзеным або сіметрычная кляча, а не для цэлых дакументаў. Гэтыя абмежэнні і ўсунуе гібрыдны падход: ствараецца тымчасовая кляча AES, пакет дадзеных шифруецца яе дапамогай, а сама кляча AES шифруецца публічной клячай RSA адправальніка, і пасля адправляюцца оба элементы. Адправальнік выкарыстоўвае свою прыватную клячу, каб адзysці клячу AES, а пасля дэшифруе пакет дадзеных. Большасць API ніколі не будзе патрабаваць гэтага ў коде прыемліка, адколькі TLS вже выкананае падобную замену, але гэта важна зразумець для сцэнарыяў кінцэ-кінцэвай шифраціі.

    4. Адзначэнне правамоўнасці і очышчэнне вхідных дадзеных

    Калі ваш API прыме даныя кліента, вы не можете прыгадаць, што можа прыйсці. Неправільна структура дадзеных, фрагменты SQL і навантажэння скрыптав можуць выглядаць як звычныя строкі, пакуль калісь не будзе ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо ўжо

    const requireContentType = (type) => (req, res, next) => {
      if (!req.is(type)) {
        return res.status(415).json({ error: "Unsupported Media Type", });
      }
    
      next();
    };
    
    app.post("/api/users", requireContentType("application/json"),
      (req, res) => {
        res.json({ message: "User created." });
      }
    );
    

    Параболічвае форму і значэнне тэлу

    Калі формат забяжаны, наступны слой пераканальваецца, чы ў запытэ ёсць правільная структура. За дапамою express-validator правілы трэба размесціць у спецыяльным модуле-параболічвальніку. Ён выкарыстоўвае сынтаксычна правільны адрес электронной пошты, асінхронна выкананае спецыяльнае пераканальванне, якое адхоўляе адресы, якія ўжо ёсць у базе дадзенаў, а таксама забяжае мінімальную дужыну пароля у восьмі символаў.

    const { body } = require("express-validator");
    const { getUserEmail } = require("../db/queries");
    
    const validateRegistration = [
      body("email")
        .isEmail()
        .withMessage("Invalid email format")
        .custom(async (value) => {
          if (await getUserEmail(value)) {
            throw new Error("Email is already in use");
          }
          return true;
        }),
    
      body("password")
        .isLength({ min: 8 })
        .withMessage("Password must be at least 8 characters long"),
    ];
    
    module.exports = { validateRegistration }
    

    Пасэк тэставання пасля таго ўкладаецца ў ланцуг мідлвэра маршрута. Унутры обробніка validationResult(req) сабірае всі неудачы, і маршрут замест таго, каб продаваць далей, вяртае код 400 з усім спискам.

    const { validationResult } = require("express-validator");
    const { validateRegistration } = require("../validators/userValidator");
    
    app.post("/api/register", validateRegistration, (req, res) => {
      const errors = validationResult(req);
    
      if (!errors.isEmpty()) {
        return res.status(400).json({ errors: errors.array() });
      }
    
      res.json({ message: "Registration successful." });
    });
    

    Санітараванне пасля верыфікацыі

    Пакалькі Express обрабоцвае мідлвэры па порядку, ланцуг санітаравання можа знаходзіцца адразу пасля верыфікацыі. Ён складаецца з выконання карэтактэраў імені і ўтэкставання яго, а таксама нормалізацыі адресы электраняўкі.

    const sanitizeRegistration = [
      body("firstName").trim().escape(),
      body("email").normalizeEmail(),
    ];
    
    app.post(
      "/api/register",
      validateRegistration,
      sanitizeRegistration,
      (req, res) => {
        const errors = validationResult(req);
    
        if (!errors.isEmpty()) {
          return res.status(400).json({ errors: errors.array() });
        }
    
        res.json({ message: "Registration successful." });
      }
    );
    

    У гэтым случае порядак мае значэнне. Перакантроль на унікальнасць у валідаторы працюе раней за normalizeEmail(), таму два варыянты напісання аднаго і таго ж адреса могу працягнуцца без перакантролі і стварыць дублікаты абанкаў. Нормалізацыя даўнае раней за пошук, або прыменэнне правіла унікальнасці да нормалізаванага значэння на рэвэле базы дадзенаў, закрывае гэтыя праслейкі. Таксама будзьце абераглівы ў выкарыстоўванні escape(): HTML-кодаванне вхідных дадзенаў заходзіць шаблоны, якія атрыбутуюць гэтыя значэння, але гэта зміняе збераглыя дадзеныя, і багатыя команды воліяць зберагаць некодаваныя значэння і кодаваць іх толькі пад час выхіднага атрыбутавання. Якщо вы разважваеце валідазныя бібліятэкі, наша параболіка Zod і express-validator раскрывае ўсе плюсы і мінусы.

    Для базы дадзенаў вярцайце параметрызаваныя запыты

    Ніколы не ствараце SQL-запыткі шляхом з’еднання даных, які вводзіць корыстнік. Кліенты баз дадзеных, такія як pg, і ORM-сістэмы, такія як Prisma, падтрымляюць параметрызаваныя запыткі, якія надаюць текст запыткі і значэнні окалічна, таму база дадзеных завжды спрыяе вводзімым данным як дацым, а не як выконвальным SQL-кодам.

    За дапамою pg стварыце пул з’яўленняў аднойчы і экспортуйце яго для вашых модуляў дадзеных:

    const { Pool } = require("pg");
    
    const pool = new Pool({
      connectionString: process.env.DATABASE_URL,
    });
    
    module.exports = pool;
    

    Запиты выкарыстоўваюць нумераваныя месца падставы ($1, $2) з значэннямі, якія падаюць як адзінлівы масіў. Нават якщо email містіць цітатку, а пасля яе — DROP TABLE, гэта зберагаецца як літэральны строк.

    app.post("/api/users", async (req, res) => {
      const { email, name } = req.body;
    
      await pool.query(
        "INSERT INTO users (email, name) VALUES ($1, $2)",
        [email, name]
      );
    
      res.status(201).json({ message: "User created." });
    });
    

    Разам этыя элементы ствараюць многослойную систему обробкі. Express-validator дазваляе выдзельваць правіла як відновімыя елементы, які працуюць як мідлвэр і фіксуюць кожную неудачу, а параметрызацыя значыць, што нават даны, якія працягнуліся праз верыфікацыю, не можу змяніць вашы запиты.

    5. Обмежэнне частоты запытоў

    Обмежэнне частоты запытоў паказвае максымальную колькасць запытоў, якія кліент можа адправіць за певны період часу. Яно зменшае ризык атак типу brute-force і denial-of-service, а таксама не дазволяе аднаму інтэнсіўнаму корыстніку перасланцаваць ресурсы для іншых.

    Обмежэнні можна застаўляць па разных крітэрыях:

    • Па кліенту: запыты лічыцца па кожнам ключы API або IP-адрэсе. Калі кліент досягае максімуму, ён чакае, пакуль період часу не перазапускаецца, або адскарыгваецца на вышэйшую квоту, часта на платным тарифе.
    • Па геаграфіі чыра часе: ліміты разлічаюцца залежна ад регіону чыра часовага перыяда, напрыклад, дазваляючы большы ўвоз дадзеных з регіонаў, дзе працуюць вашы кліянты, і згружаючы ліміты там, дзе выходзіць падазроўны трафік.
    • Па ўместнасці сервера: дзеяныя часткі API направляюцца на спецыяльную інфраструктуру з саеўнымі лімітамі, такімі як маленькі пул фонавых працоўнікаў для дорогіх заданняў.

    Існуе многа алгорытмаў (фіксаваны вікна, скользячы вікна, token bucket), і вам не трэба самім іх рэалізаваць, каб пачаць. Мідлвэр express-rate-limit за замовчаннем пісае колькість запыткаў па кожнам IP-адрэсе. У прыкладзе нижэй заданы загальны ліміт у 100 запыткаў за 15 хвілін для всіх ресурсаў пад /api, а таксама значна строгія норма — пяць спроб за пяць хвілін для аблогавання, з індывідуальным паведамленнем для адхілёваных запыткаў.

    const rateLimit = require("express-rate-limit");
    
    // Apply to all API routes
    const apiLimiter = rateLimit({
      windowMs: 15 * 60 * 1000, // 15 minutes
      max: 100,
    });
    
    // Apply stricter limits to authentication endpoints
    const loginLimiter = rateLimit({
      windowMs: 5 * 60 * 1000, // 5 minutes
      max: 5,
      message: "Too many login attempts. Please try again later.",
    });
    
    app.use("/api", apiLimiter);
    
    app.post("/api/login", loginLimiter, (req, res) => {
      res.json({ message: "Login successful." });
    });
    

    Публічныя API зазвычай выдаюць кожнаму корыстніку ключ, і обмежэнне па гэтым ключы є справядлівейшым, чым обмежэнне па IP-адрэсе, адколькі багато корыстнікаў можа выкорыстоўваць адну адрэсу через корпаратыўны проксі. Спецыяльны keyGenerator чытае заголовак X-API-Key і выкарыстоўвае яго як ідэнтыфікатор лічыльніка.

    const rateLimit = require("express-rate-limit");
    
    const apiKeyLimiter = rateLimit({
      windowMs: 15 * 60 * 1000,
      max: 1000,
      keyGenerator: (req) => req.get("X-API-Key"),
    });
    
    app.use("/api", apiKeyLimiter);
    

    Як напісана, кожны запит, які не маюць заголовка, стварае той самы ключ undefined і викорыстоўвае аднаковы бакет. У практыцы трэба адхіліць запиты без ключа раней у ланцюгу обробкі або перайсці на викорыстанне IP-адресы.

    Обмежэнне швайна дорогіх канцэнтраў

    Обмежэнне швайна вплывае на тое, насколькі шыбкаа прыймаюцца запиты, каб раптовы сплескі не перавантажылі сервіс. У наступной настройцы викорыстоўваецца той самы мідлвэр з дужа короткімі інтерваламі: максымум дзесяць запытоў за секунду па всім API, і толькі адзін запыт на пошук кожныя две секунды на кліента, таму што пошук ёсць найбольш ресурсамі інтэнсіўным канцэнтрам.

    const rateLimit = require("express-rate-limit");
    
    // Throttle all API requests
    const apiThrottle = rateLimit({
      windowMs: 1000, // 1 second
      max: 10, // Allow up to 10 requests per second
    });
    
    // Apply a stricter throttle to resource-intensive endpoints
    const searchThrottle = rateLimit({
      windowMs: 2000, // 2 seconds
      max: 1, // Allow 1 request every 2 seconds
      message: "Please wait before sending another search request.",
    });
    
    app.use("/api", apiThrottle);
    
    app.get("/api/search", searchThrottle, (req, res) => {
      res.json({ results: [] });
    });
    

    Строга гаворка, гэта яшчэ ўсё ўскорбленне частоты запытоў з малымі інтерваламі: занадто большыя запыты адхоўляюцца з кодам 429, а не з затрымкай. Якщо вы хочаце справжняе ускорбленне, якое спамтавае кліенты пры першым жа запыте, а не пасля адхоўлення, то пакеты на кшталт express-slow-down даўаюць можлівасць стварыць поступовыя затрымкі. Таксама згадаць, што стандартны внутрашній база дадзеных лічыць запыты па процэсу, таму за лоад-балансерам з калькама інстанцый вам патрэбна спяльная база дадзеных, такая як Redis, каб ліміты застаўаліся актуальнымі. Няўяроўныя выданні express-rate-limit таксама называюць опцыю max як limit; пераканайцеся ў даследжэнні да версіі, яку вы інсталюеце. Для лёгкага альтэрнатываў у формате TypeScript, адзірніце нашу статыю пра мінімальны лімітар частоты запытоў для Express.

    6. Логаванне, манітарынг і выяўленне інцыдэтаў

    Вы не можете адактувацься на атаку, якой ніколі не бачылі. Логаванне фіксуе запыты і адказы разам з іх метаданнымі, контэкстам, часамы і кодамі адказаў, тады вы можете выканаць діагностику, аудыт і зрозумець рэальную стаўку выкарыстоўвання. Монітарынг стежыць за актывасцю у рэальны час, фіксуе такія паказнікі, як затрымкі, частка адказаў з адказамі і праўільнасць обробкі, і выяўляе анамаліі, якія можуць сведчыць пра зловжывання, недасягненне цэляў на рэвэле цыркуляцыі або адкрытую слабасцю.

    Галоўныя падходы з іх перакананнямі:

    • Логаванне запытоў за дапамогою мідлвэра, такога як Morgan, дышчыльна фіксуе кожны прыходзячы HTTP-запыт, але не дае інфармацыі пра стан системы.
    • Логаванне аплікацыі за дапамою Winston, Pino чыста Bunyan фіксуюць бізнес-і безпековыя падзеі, такія як запускі, операцыі з базайнамі дадзеных і памылкі. Большыя системы патрабуюць структураванага выходу і цэнтрызаванага зберагчыка, каб ён быў корыстным.
    • Метрыкі за дапамою Prometheus і Grafana стежыць за частотай запытоў, затрымкамі, CPU, памяцю і частотай памылак. Яны паказваюць агрэгаваныя тэндэнцыі, але не тое, што адбылася ў аднам запыте.
    • Цэнтрызаваная адарожчанне логаў за дапамою ELK Stack, OpenSearch, Splunk чыста CloudWatch агрэгуе логі з разных служб, але гэта выклікае патрэбу ў дадатковай інфраструктуре і дапамогу ў ўтрыманні.
    • Монітарынг выконвання аплікацыі за дапамою Datadog, New Relic чыста Dynatrace спаўнае логі, метрыкі, трэйсы і апавешчэнні ў адной платформе, але гэта супакоўвае вышэйшыя вартасці ліцэнзавання і большую складнасць платформы.

    Будзь-канэ з іх падключаецца да Express. Далей паказаны чатыры популярныя складовыя элементы.

    Логаванне запытак з Morgan

    Рэўістрацыя Morgan у формате combined запісвае лінію у стыле Apache для кожнай запыткі, уключаючы метод, шлях, статус, размер адпаведзі і user agent.

    const express = require("express");
    const morgan = require("morgan");
    
    const app = express();
    
    // Log every incoming request
    app.use(morgan("combined"));
    
    app.get("/api/users", (req, res) => {
      res.json({ message: "Users retrieved successfully." });
    });
    

    Структураваныя логіі застою з Winston

    Winston фіксуе падзеі як структураваныя об’екты. Запіс ідэнтыфікатаў корыстніка і замовлення пад час стварэння замовлення стварае летак аудыту, які можна пазнічэй шукаць.

    const winston = require("winston");
    
    const logger = winston.createLogger({
      transports: [
        new winston.transports.Console(),
      ],
    });
    
    app.post("/api/orders", (req, res) => {
      logger.info("Order created", {
        userId: req.user.id,
        orderId: req.body.id,
      });
    
      res.status(201).json({ message: "Order created." });
    });
    

    Будзьце абярожны ў тым, што падае ў логі. ID пользователяў ў порядку; паролі, токены, цэлыя номеры картак і весь тэкст запыткаў — ні. Логі ўсё часта стаюць месцам вытэкання чутлівых дадзэнняў.

    Цэнтрызаваная логізацыя адзінакоў

    Мідлвэр для обработкі адзінакоў у Express, які можна адрасаваць за чатырма аргументамі, ловіць адзінакі з любога маршруту. Ён запісвае прычыну адзінака разам з памятай маршруту і методам і вяртае стандартны код 500, так што стэк-трэсы і внутрашнія деталі ніколі не дасягаюць кліента.

    app.use((err, req, res, next) => {
    /* Logger is built as an independent module or class */
      logger.error(err.message, {
        path: req.originalUrl,
        method: req.method,
      });
    
      res.status(500).json({
        error: "Internal Server Error",
      });
    });
    

    Адаптаванне метрык для Prometheus

    Бібліятэка prom-client саўеруе стандартныя метрыкі процэса Node.js і выкладзе іх на канцэнтры /metrics, каб Prometheus могаў іх збіраць.

    const client = require("prom-client");
    
    client.collectDefaultMetrics();
    
    app.get("/metrics", async (req, res) => {
      res.set("Content-Type", client.register.contentType);
      res.end(await client.register.metrics());
    });
    

    Этот канцэнтрык апавяроўвае внутршні дакладнасці пра вашу службу, таму яго трэба абмежыць вашай сеткай манітарынгу або разместіць за аутэнтыкацыяй, а не заліць яго публічным.

    У такіх випадках дапамагаюць фрэймворкі з ужо налаштаванымі рашэннямі. NestJS прыносіць з сабой вбудованы логгер і структуру, якая спрыяе прыўязцы логавання і метрык да кожнага канцэнтрыка, тады як у фрэймворку без такіх налаштаванняў, як Express, трэба самастоятельна дадаць логаванне, зазвычай у вачынку мідлвэра, які працюе перад адправкай адпаведзі.

    Адкрыць інцыдэтаў ствараецца на адной з гэтых лог-даных: апавешчэнні пра маршруты з падозрэльнымі патэранамі, такімі як растышчэнне колькасці 401 адпаведзей аб адхіленніх з-за лімітаў частоты, надаюцца у канал апавешчэння, які фактычна стежыць ваша команда.

    Безпека як непаўзлівы процес

    Няма жаднага артыкула, які б пакрыў усё, але пры якім-небудзь выпуску вы можете пераканацца, што ваш API адпавядае гэтаму базоваму стандарту:

    • Кожны канцэнтры обслужваюцца толькі через HTTPS.
    • Выкарыстоўваецца OAuth або адпоўнайна эквівалентны механізм токенаў.
    • Выданые JWT-ы маюць тэрмін дзейнасці.
    • Ліміты заходзяць усім маршрутам, пры чым на процес заходжання ў систему ліміты ўжо строгіяй.
    • Кожны вхідны даны прабываюць перавернутыя пры ўжыцці.
    • Запыты працавалі праз тэсты на спробы втрымкі.
    • Правіла доступу таксама працавалі праз тэсты, укладаючы перакананні на рэвэлеўні об’ектаў.
    • Клучы і секрэты знаходзяцца за межамі кодавой базы.
    • Эвенты, якія стосуюцца безпекі, фіксуюцца ў логах.
    • Настроены панелі керування і апавешчэнні.
    • У адпаведзях є загаловкі безпекі.
    • Кліенты ніколі не бачаць трэс-трэйсоў чы дакладнасці внутраніх адзінакоў.
    • Залежнасці ў стацыонарным стане і працавалі праз аудыт.

    У прыкладах тут быў выкарыстан Express, але тыя ж ідэі прыемлімы і для іншых фрэймворкаў бэкэнду, большасць з якіх або безпасэчна інтегруюць гэтыя інструменты, або прысвойваюць іх адпаведнікі. Напрыклад, NestJS керуе верыфікацыяю запытак через об’екты перадачы дадзэнняў. У дасведчэннях вашага фрэймворка будзе паказана стандартная версія кожага слоя.

    Тыя ж прынцыпы служають асновай для размешчэння на платформах у стылі «cloud-native», такіх як Azure, Google Cloud і AWS, якія дадаюць свае сопрацоўнікі, службы ідэнтыфікаціі та кераваныя механізмы обмежэння частоты запытак. Практыкі, спецыфічныя для хмары, заслуговуюць на аднародную адгукаванне, але вышэўзгаданыя слоі вже значна спрыяюць прыняццю API пасля перагляду з точкі зору безпекі.

    Короткі аудыт безпекі API Express

    • Раздзеляйце перагляд аутантыкацыйных дакументаў і аутентыфікацыю за кожны запыт: раз апрацаваце пароль, а потым паверніцеся да тымчасовых падписаных токэнаў.
    • Автанацыя — гэта не автарызацыя. Пераканаўце дыяпазоны і ролі, а таксама пераканаўце права ўласнасці кожнага об’екта, які паўтараецца ў запытэ.
    • Для дадзей, якія знаходзяцца у стане спакою, выкорыстоўваюце AES-GCM з унікальным IV для кожнай операцыі; асиметрычную шифрацыю застаўляйце для малых значэнняў і абмены ключамі.
    • Даўжынай выконвайце перакананні на тып кантэнту, яго перакананне, очышчэнне і параметрызаваныя запыты, а таксама задумайцеся пра порядак іх выканання.
    • Установіце ліміты на частоту запытоў для всего, прыкладзіце стрэльнейшыя ліміты да процэсаў заходжання і дорогіх канцэнтраў, а калі запускаеце больш адной інстанцыі — выкорыстоўваюце спяльны хранільнік.
    • Фіксуйце ў логах падзеі, якія маюць значэнне для безпекі, не фіксуючы секрэты, і ператворыце гэтыя логі на апавешчэнні, на якія хтось будзе рэагаваць.

    Супаўзеўныя матэрыялы

  • Автанацыя з біаметрычнымі дадзеннямі на iOS і Android з ключамі, прычыплённымі да апаратуры: Дазвольце дазнацца, чаму сама тэхналогія Face ID не паводзіць нічога для вашага сервера, і як выкарыстоўваць Secure Enclave і ключы Android Keystore для падписвання разовых запитоў сервера.
  • Ад аплоаду да URL: Безпечнае зберагчэнне і выдача файлаў корыстнікаў у Express: Дазвольце дазнацца, дзе аплікацыі Express павінны зберагчыць аплоадаваныя файлы, як express.static супараднуючы каталог з URL-адрэсамі, і якія захоўніцкія меры запобегаюць таму, каб аплоадаваныя файлы корыстнікаў сталі аб’ектамі абавясці бяспекі.
  • Контроль даступу на адміністратыўнай аснове ў Express за дапамогою JWT і двух мідлвэраў: Дазнаецеся, як застаўіць контроль даступу на адміністратыўнай аснове ў API Express, спалучыўшы мідлвэр аутантыкацыі JWT з можна-павтарна-выкарыстоўваным функцыям authorize(), а таксама калі трэба вярнуць код 401, а калі 403.
  • Перанесенне JWT у React-аплікацыі з localStorage у HttpOnly-кучкі: Дазнаецеся, чаму JWT у localStorage ўразлежны ад атак типу XSS, як HttpOnly-кучкі з параметрамі SameSite, ротацыяй і BFF зменшаюць рызык, і якія проблемы застаюцца ў React-аплікацыях.