Ограничение скорости для облачных функций Google / Firebase? - PullRequest
0 голосов
/ 07 июня 2018

Я использую Firebase для разработки приложения, которое использует облачные функции в качестве REST API для внутреннего использования.Мой вопрос заключается в том, существует ли простой способ реализации ограничения скорости на IP / пользователя, аналогично тому, что slack использует , за исключением на IP и на пользователя на основе, а не на приложение (поскольку все это одно приложение).Также предпочтительной является поддержка небольших пакетов.

Пример кода (см. // TODO: комментарии):

exports.myCoolFunction = functions.https.onRequest((req, res) => {
        // TODO: implement IP rate-limiting here
        unpackToken(req).then((token) => { // unpackToken resolves with a response similar to verifyIdToken based on the "Authorization" header contents
                // TODO: implement user-based rate-limiting here (based on token.uid)
                if (!req.body) return res.status(400).end();
                if (typeof req.body.name !== "string") return res.status(400).end();
                if (typeof req.body.user !== "string") return res.status(400).end();

                // more input sanitization and function logic here

                return res.status(501).end(); // fallback in all requests, do not remove
        }).catch(() => res.status(403).end());
});

Я хочу завершить запрос просто с помощью кода состояния 529 Too Many Requestsесли лимит скорости превышен.Это сделано для предотвращения переполнения сети ошибками приложений и предотвращения злоупотребления API REST.

Это должно учитывать учет вращения и отключения экземпляров сервера Firebase и одновременную работу нескольких экземпляров.

Я также использую базу данных Firestore и при необходимости могу использовать устаревшую базу данных реального времени.

Ответы [ 2 ]

0 голосов
/ 29 июля 2019

Я создал библиотеку для вызовов ограничения скорости для функций firebase: firebase-functions-rate-limiter Библиотека использует realtimeDB или firestore (настраивается) в качестве бэкэнда.Он хранит данные в том же подходе, который описал Фрэнк, но более экономичен.Вместо использования коллекции он использует один документ с массивом для каждого спецификатора (например, идентификатор пользователя).Это означает, что существует только одно чтение для превышенного вызова и чтение-запись для разрешенного вызова.

$ npm i --save firebase-functions-rate-limiter

Вот пример:

import * as admin from "firebase-admin";
import * as functions from "firebase-functions";
import { FirebaseFunctionsRateLimiter } from "firebase-functions-rate-limiter";

admin.initializeApp(functions.config().firebase);
const database = admin.database();

const limiter = FirebaseFunctionsRateLimiter.withRealtimeDbBackend(
    {
        name: "rate_limiter_collection",
        maxCalls: 2,
        periodSeconds: 15,
    },
    database,
);
exports.testRateLimiter = 
  functions.https.onRequest(async (req, res) => {
    await limiter.rejectOnQuotaExceeded(); // will throw HttpsException with proper warning

    res.send("Function called");
});
0 голосов
/ 07 июня 2018

Выполнение этого для каждого пользователя звучит довольно просто:

  1. Передача токена ID пользователя в облачные функции с каждым запросом.
  2. Декодирование токена ID в вашемОблачная функция для определения UID.Пример этих первых двух шагов см. functions-samples repo .
  3. . Подтолкните тот факт, что пользовательский UID вызвал функцию для базы данных, возможно, добавив ее в список.Например, admin.database().ref(`/userCalls/$uid`).push(ServerValue.TIMESTAMP).
  4. Запросить количество последних вызовов, например, admin.database().ref(`/userCalls/$uid`).orderByKey().startAt(Date.now()-60000).
  5. Подсчитать результаты и отклонить, если оно слишком высокое.

Я не уверен, что IP-адрес звонящего передается в облачные функции.Если это так, вы можете сделать ту же логику для IP-адреса.Если он не будет пройден, будет сложно оценить лимит таким образом, чтобы его нельзя было легко подделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...