Как обрабатывать авторизацию на основе функций и разрешений в Next.js без задержки первоначального рендеринга?

Я создаю мультитенантное SaaS-приложение с Django Ninja в качестве серверной части и Next.js в качестве интерфейса. Я столкнулся с проблемой, связанной с обработкой разрешений RBAC и прав на функции организационного уровня, не вызывая плохого поведения пользовательского интерфейса.

Текущая настройка

  • Приложение имеет заранее определенный набор разрешений и функций.
  • Каждая организация может:
    • Создайте свои собственные роли RBAC для участников.
    • Определяют свои собственные планы (пакеты функций) для участников.
  • Иерархия выглядит следующим образом: Платформа → Организация → Участники.

Проблема

Для RBAC я сначала попытался получить разрешения / функции из API после входа в систему. Но в Next.js это вызвало проблему с UX:

  • При первоначальном рендеринге пользовательский интерфейс отображал все компонентов/функций.
  • Только после разрешения вызова API (или обновления вручную) пользовательский интерфейс обновился, чтобы скрыть компоненты с ограниченным доступом.
  • Это привело к эффекту мерцания, когда пользователи на короткое время увидели компоненты, которых не должны были видеть.

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

Вопрос

  • Допустимо ли также указывать права на использование функций в JWT (и обновлять токен при изменении организации/плана)?
  • Или есть лучший шаблон для предварительной загрузки прав в Next.js , чтобы компоненты отображались корректно при первой загрузке без мерцания?
  • Как люди обычно справляются с этой комбинацией RBAC (на уровне пользователя) и функциональных флагов (на уровне организации) в многопользовательском-условия SaaS для арендаторов?

Основные ограничения

  • Пользовательский интерфейс должен корректно отображаться при первой загрузке (без мерцания).
  • Я не хочу раздувать JWTS без необходимости.
  • Я придерживаюсь принципа “доверяй, но проверяй” → JWT удобен для мгновенных проверок, но серверная часть по-прежнему проверяет права.

tldr: используйте SSR.

  • Маршрутизатор страниц: Получает запросы на сервер, если это всего лишь пара страниц, и Получает исходные запросы, если это нужно для каждой страницы
  • Маршрутизатор приложений: Я полагаю, что вы можете использовать макеты для извлечения данных и передачи их на остальную часть веб-сайта; они также могут быть вложенными, и вы могли бы реализовать только часть веб-сайта в приложении / маршрутизаторе, оставив остальное в pages /, хотя это может быть немного сложно настроить, будьте осторожны потому что ему действительно нравится пропускать повторную визуализацию

Возможно, это не самое чистое решение, но, по крайней мере, оно должно сработать.
Я предполагаю, что в какой-то момент вы в конечном итоге загрузите пользователя из серверной части, чтобы отобразить имя, аватар и т.д. Так почему бы не предварительно загрузить его на серверную часть (NextJS) на этапе SSR, чтобы запросы можно было кэшировать, пользовательский интерфейс был предварительно обработан, не нужно загромождать JWT дополнительными данными. Что касается авторизации, вы можете просто прочитать файл cookie клиента в обработчике SSR и передать его серверной части в заголовке авторизации. При необходимости промежуточное программное обеспечение на сервере может преобразовать его в файл cookie (в конце концов, это просто еще один заголовок), так что вам даже не придется изменять для этого какие-либо серверные настройки.
Еще одним плюсом этого метода является то, что если вы размещаете свой сервер и внешний интерфейс вместе на одном компьютере, NextJS может напрямую взаимодействовать с вашим внутренним интерфейсом, поэтому передача данных пользователя с сервера на сервер будет еще быстрее, чем отправка этого запроса с внешнего интерфейса.
Наконец, если вы используете OpenApiGenerator, вы можете изменить клиент таким образом, чтобы он автоматически выбирал правильный адрес (https://api.yourAwesomeProject.com или http://api_container_name:5000 /) для сервера на основе наличия объекта window и принимает необязательный аргумент для клиентских файлов cookie для пересылки при необходимости.

Примечания:

  1. Если вы используете getInitialProps, имейте в виду, что когда пользователь переходит между страницами с помощью кнопок nextLink или "назад"/"вперед" (в браузере), он запускается во внешнем интерфейсе, внутри которого вы можете проверить, не определено ли значение window, чтобы различать сценарии
  2. полезные ссылки о app router предварительный рендеринг , макеты , выборка данных
  3. Такую глобальную информацию, как user, действительно удобно иметь в ReactContext
  4. Если вы хотите обновить пользователя позже, не обновляя страницу, вы можете объединить ReactContext с UseSWR, он принимает аргумент initialValue (вы передаете его из SSR) и может быть настроен на повторную выборку пользователя по определенным теггерам, я бы настоятельно рекомендовал создать перехватчик useUser на основе ReactContext и SSR, который предоставлял бы доступ к любым методам, связанным с изменением пользователя. документы swr
Вернуться на верх