Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як захистити GraphQL API від дорогих і зловмисних запитів?

GraphQL дає клієнту змогу самому будувати запит - а отже й побудувати дуже дорогий. Один HTTP-запит може змусити сервер виконати мільйони операцій.

Типові атаки й проблеми:

# глибина: циклічні зв'язки дають експоненційне зростання
{ user(id: 1) { friends { friends { friends { friends { name } } } } } }

# ширина: величезні списки
{ posts(first: 100000) { comments(first: 1000) { author { name } } } }

# псевдоніми: одне поле, викликане тисячу разів в одному запиті
{ a1: login(email: "...", password: "1") a2: login(email: "...", password: "2") ... }

Останній приклад обходить обмеження частоти на рівні HTTP: один запит - тисяча спроб входу.

Захист - кілька рівнів:

  • обмеження глибини запиту (наприклад, 8-10 рівнів);
  • аналіз складності: кожному полю призначається «вартість» (списки - помножена на first), запит понад ліміт відхиляється до виконання;
  • обов'язкова пагінація з максимумом - жодних списків без first чи з first: 100000;
  • обмеження частоти за складністю, а не за кількістю HTTP-запитів: бюджет «очок» на клієнта за хвилину (так працює GitHub GraphQL API);
  • обмеження псевдонімів і пакетних запитів (batching кількох операцій в одному HTTP-запиті);
  • тайм-аути виконання запиту.

Інтроспекція в продакшені. Вона показує всю схему, включно з внутрішніми полями й мутаціями. Для публічних API зі схемою як документацією це нормально; для API лише свого фронтенду - вимкнути.

Збережені (persisted) запити / довірені документи: клієнт надсилає не текст запиту, а його хеш з переліку, відомого серверу під час збирання. Сервер виконує лише заздалегідь відомі запити - довільні атаки неможливі взагалі. Найсильніший захист для API, яке використовує лише ваш фронтенд, плюс бонус - запити можна робити через GET і кешувати на CDN.

Авторизація на рівні полів. Перевірка лише на верхньому запиті недостатня: доступ до order не означає доступу до order.customer.paymentMethods. Кожен резолвер чутливих даних має перевіряти права.

Повідомлення про помилки: у продакшені не віддавати стек і внутрішні деталі в errors - це витік інформації про реалізацію.

У Lighthouse обмеження задаються в config/lighthouse.php (max_query_depth, max_query_complexity, disable_introspection), а вартість полів - директивою @complexity. За замовчуванням ліміти вимкнені - їх треба ввімкнути свідомо.

Докладніше в документації: Безпека GraphQL

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання