Firebase - лучшая практика для чтения файлового хранилища сервера для рендеринга на стороне сервера - PullRequest
0 голосов
/ 07 января 2019

У меня есть приложение рендеринга на стороне сервера, использующее firebase firestore.

У меня есть область моего сайта, на которой на сервере выполняется рендеринг контента, который необходимо извлечь из firestore.

В настоящее время я использую правила пожарного депо, чтобы позволить кому-либо читать данные из этих конкретных документов

Что меня беспокоит , так это то, что какой-то плохой человек может настроить скрипт так, чтобы он просто постоянно попадал в мою базу данных с чтениями и наращивал мои счета (так как мы взимаем плату за чтение, это кажется, что никогда не стоит позволять кому-либо выполнять чтение.)

Текущее правило

// Allow anonymous users to read feeds
match /landingPageFeeds/{pageId}/feeds/newsFeed {
  allow read: if true;
}

Лучший путь вперед?

Как мне разрешить моему серверному скрипту читать из firestore, но не разрешать кому-либо еще делать это?

Имейте в виду, что это начальное действие, которое выполняется на стороне сервера, прежде чем гидратировать сторону клиента с предварительно загруженным состоянием. Эта функция / действие также предоставляется клиентской стороне для навигации по страницам.

Я рассмотрел анонимный логин - который работал, однако это создавало нового анонимного пользователя при каждой загрузке страницы - и Firebase регулирует новые адреса электронной почты / пароль и учетные записи анонимных пользователей. Это не казалось практичным.

1 Ответ

0 голосов
/ 07 января 2019

Решение

За комментарий Дуга я больше думал об админском SDK. Я закончил тем, что создал отдельный API в функциях Firebase для анонимных запросов, требующих безопасного чтения в Firestore, которое можно кэшировать.

Цель

  1. Продолжить отказать публичные чтения моей базы данных пожарного магазина
  2. Разрешить анонимным пользователям запускать чтение из Firestore для отображаемых на стороне сервера страниц реагирования, для которых требуются данные из базы данных Firestore (например, для новых посетителей и поисковых систем).
  3. Запретить " read spam ", когда третья сторона может получить доступ к моей базе данных миллионами операций чтения, чтобы повысить мои облачные затраты, используя серверный кэш CDN для ответов. (вызывая неестественные чтения в цикле, я однажды наложил огромный счет на несчастный случай - я хочу удостовериться, что незнакомцы не могут сделать это злонамеренно)

Кэширование Admin SDK и функции Firebase

Admin SDK позволяет мне безопасно читать из firestore. Мои правила безопасности firestore могут запрещать доступ неаутентифицированным пользователям.

Функции Firebase, которые обрабатывают GET запросы на поддержку сервер, кэширующий ответ . Это означает, что последующие обращения от идентичных запросов не будут перезапускать все мои функции (чтение из firebase, другие вызовы функций) - он просто мгновенно ответит теми же данными снова.

Процесс

  1. Анонимный клиент посещает серверную страницу обработанной реакции
  2. Первоначальный рендеринг нагрузки на сервер запускает функцию firebase (триггер https)
  3. Функция Firebase использует Admin SDK для чтения из защищенной базы данных пожарного хранилища
  4. Функция кэширует ответ на 3 часа res.set('Cache-Control', 'public, max-age=600, s-maxage=10800');
  5. Последующие запросы от любого клиента в любом месте в течение следующих 3 часов поступают из кэша - избегая ненужных чтений или дополнительного использования вычислений / ресурсов

Примечание - кэширование не работает на локальном компьютере - необходимо развернуть его в firebase для проверки эффекта кэширования.

Пример функции

const functions = require("firebase-functions");
const cors = require('cors')({origin: true});
const { sendResponse } = require("./includes/sendResponse");
const { getFirestoreDataWithAdminSDK } = require("./includes/getFirestoreDataWithAdminSDK");


const cachedApi = functions.https.onRequest((req, res) => {
    cors(req, res, async () => {
        // Set a cache for the response to limit the impact of identical request on expensive resources
        res.set('Cache-Control', 'public, max-age=600, s-maxage=10800');

        // If POST - response with bad request code - POST requests are not cached
        if(req.method === "POST") {
            return sendResponse(res, 400);
        } else {

            // Get GET request action from query
            let action = (req.query.action) ? req.query.action : null;
            console.log("Action: ", action);

            try {
                // Handle Actions Appropriately
                switch(true) {

                    // Get Feed Data
                    case(action === "feed"): {
                        console.log("Getting feed...");

                        // Get feed id
                        let feedId = (req.query.feedId) ? req.query.feedId : null;

                        // Get feed data
                        let feedData = await getFirestoreDataWithAdminSDK(feedId);

                        return sendResponse(res, 200, feedData);
                    }

                    // No valid action specified
                    default: {
                        return sendResponse(res, 400);
                    }
                }
            } catch(err) {
                console.log("Cached API Error: ", err);
                return sendResponse(res, 500);
            }
        }
    });
});

module.exports = {
    cachedApi
}
...