Перенос логики работы с БД из серверной части в клиентскую
Возник неоднозначный вопрос касательно клиент-серверной архитектуры:
Вводные:
- Пишет все 1 разработчик (backend и frontend).
- Единица измерения эффективности - время разработки (например, изменить код в клиенте быстрее, чем изменить его на клиенте и сервере).
В большинстве сайтов\приложений, которые я пишу, прослеживается следующая логика:
- Клиент - несет в себе логику отображения данных. Например, при нажатии кнопки - клиент запрашивает у сервера список объектов (передавая в параметрах запроса параметры выборки) и затем отображает клиенту.
- Сервер - несет логику "прослойки" между БД и клиентом, предоставляя роуты доступа (с методами для работы с GET, POST и т.д). Например, сервер получает запрос
GET https://domain.com/usersс параметрами выборки (offset, columns), парсит эти параметры в SQL запрос, достает из БД список пользователей и возвращает обратно клиенту. - Сервер - хранит данные. Здесь понятно.
В какой-то момент я пришел к выводу, что клиент и сервер дублируют логику друг друга. Условно говоря, клиент имеет функционал для доступа к URL'y /users/ (с методам getUsers(), removeUser(id) и т.д.), а сервер предоставляет роуты (с методам get(users), delete(user) и т.д.) для работы с таблицей users.
Ради интереса, я изменил логику сервера, чтобы был только один роут доступа к данным: https://domain.com/database.
В качестве параметров, этот роут принимает:
- Название таблиц(-ы) (в нашем случае
users, но можно сделать иjoin). - Параметры для выборки данных (метод select\delete\etc., параметры where, offset, sort и т.д. в виде JSON-объекта).
- Данные пользователя. При запросе через этот роут, сервер проверяет, авторизован ли пользователь и имеет ли он доступ к таблицам (например, пользователь с правами
userможет получить только доступ к базеusers, но не кstaffи т.д.).
При каждом запросе проверяется авторизация и проверка параметров на SQL-инъекцию (чтобы не прошел параметр method: "SELECT * FROM users; -- ").
В результате, если раньше сервер имел логику настройки роутов и проверки данных - отпала логика настройки роутов и дублирования методов GET, POST и т.д. для каждой таблицы. Теперь есть только 3 универсальных метода GET POST DELETE для всей базы данных.
Однако, видимо, есть причины, почему такая практика не получила распространения. Первая мысль - возможны проблемы с защитой. Но авторизация и проверка данных на SQL инъекции осталась. Грубо говоря, разницы между двумя вариантами в плане защиты нет.
Вопрос: почему так не делают? Какие минусы у такого подхода, что может пойти не так и следует ли дальше использовать такой подход?
Возможный ответ: почему нельзя! Можно! Есть же Google Firebase!
Уточнение: вопрос довольно объемный и однозначного ответа нет. Поэтому готов обсуждать любые утверждения в ответах\комментариях, чтобы "дойти" до истины.
Ответы (2 шт):
- Раскрывается структура БД для конечного пользователя.
- Жесткая привязка всей программы к конкретной структуре БД. Нельзя переименовать поле таблицы, разделить или объединить таблицы, вынести какие-либо данные в другие БД (например, с целями кеширования) без поиска и изменения всех мест где есть использование затронутых структур.
- Подозреваю, что избыточное дублирование кода в разных частях такой программы и усложнение чтения кода. Вместо GET /user/{id} надо писать полноценный SQL запрос да еще в нестандартном виде.
- Привязка к одной СУБД, нельзя написать еще одну "прослойку" для другой базы, которая внешне реализует те же методы что и первая, но внутри использует совсем другую БД. Как был у неё get(users) так и остался, но внутри совсем другая обработка.
Тебе понадобится сервер с row level security. Потому что если без - все проверки и ограничения на клиенте будут бесполезны. Клиент заведомо неподконтролен, любой мамкин хакер возьмет curl и отправит запрос на твой сервер для получения не предназначенных ему данных.
В случае наличия полноценного backend ты можешь регулировать всё что захочешь - кэширование, балансировка, аутентификация разными методами и другие ручки, которые не будут доступны тебе, если клиент будет напрямую лазить в БД. Потому что см. п.1 - обязательно и очень быстро найдутся желающие потрогать СУБД поплотнее в части не принадлежащих им данных. По сути бакенд это изоляция клиента от конкретной реализации механизмов обработки и хранения. Имея бакенд ты можешь делать клиентов на разных языках и платформах, которые смогут использовать одно и то же API. И все обновления бакенда никак не повлияют на клиентов, потому что у них есть API.
Представляется некоторые сложности с логированием в случае прямого доступа к СУБД. Кто какие запросы отправил, где, кто и когда что поменял.