Стратегии аутентификации в Next.js

Процесс аутентификации - это процесс проверки, кем является пользователь, а процесс авторизации контролирует, к чему пользователь может получить доступ. Next.js поддерживает несколько шаблонов аутентификации, каждый из которых предназначен для совершенно разных вариантов использования. На этой странице будет рассмотрен каждый случай, чтобы вы могли выбрать для своего проекта подходящий исходя из своих ограничений.

В

Вадим Пашаев

4/13/2022

Стратегии аутентификации в Next.js

Перевод документации

Процесс аутентификации - это процесс проверки, кем является пользователь, а процесс авторизации контролирует, к чему пользователь может получить доступ. Next.js поддерживает несколько шаблонов аутентификации, каждый из которых предназначен для совершенно разных вариантов использования. На этой странице будет рассмотрен каждый случай, чтобы вы могли выбрать для своего проекта подходящий исходя из своих ограничений.

Паттерны аутентификации

Первый шаг к тому, чтобы определить, какой шаблон аутентификации вам нужен, — это понять, какую стратегию выборки данных вы хотите использовать. Затем мы можем определить, какие поставщики аутентификации поддерживают эту стратегию. Существует два основных шаблона:

  • Использование статической генерации страницы на сервере с последующей подгрузкой данных о пользователе на стороне клиента;
  • Извлечение пользовательских данных на стороне сервера, чтобы устранить появление неаутентифицированного контента.

Аутентификация статически сгенерированных страниц

Next.js автоматически определяет, что страница является статической, если нет требований к блокирующим данным. Об этом говорит отсутствие на странице функций getServerSideProps и getInitialProps. Вместо этого ваша страница может отображать состояние загрузки данных на пришедшей с сервера странице, а затем получать данные пользователя на стороне клиента.

Одним из преимуществ этого паттерна является то, что он позволяет обслуживать страницы из глобальной CDN и предварительно загружать их с помощью next/link. На практике это приводит к более быстрому TTI (Time to Interactive).

Давайте рассмотрим пример страницы профиля. Он изначальное отобразит загрузочный скелет и как только запрос пользователя будет завершен, он покажет имя пользователя:

// pages/profile.js import useUser from '../lib/useUser' import Layout from '../components/Layout' const Profile = () => { // Получение пользовательских данных на клиенте const { user } = useUser({ redirectTo: '/login' }) // То, что будет рендериться на сервере if (!user || user.isLoggedIn === false) { return <Layout>Загрузка...</Layout> } // После того, как данные пользователя будут загружены, отобразится содержимое страницы ниже return ( <Layout> <h1>Ваш профиль</h1> <pre>{JSON.stringify(user, null, 2)}</pre> </Layout> ) } export default Profile

Посмотреть этот пример в действии вы можете на странице.

Аутентификация при SSR

Если вы экспортируете асинхронную функцию getServerSideProps со страницы, Next.js будет предварительно рендерить эту страницу при каждом запросе, используя данные, возвращаемые getServerSideProps.

export async function getServerSideProps(context) { return { props: {}, // Будут переданы в компонент страницы через props } }

Давайте преобразуем пример загрузки данных пользователя, чтобы использовать рендеринг на стороне сервера. Если есть сеанс, верните пользователя в качестве опоры для компонента «Профиль» на странице. Обратите внимание, что в этом примере нет скелета загрузки.

// pages/profile.js import withSession from '../lib/session' import Layout from '../components/Layout' export const getServerSideProps = withSession(async function ({ req, res }) { const { user } = req.session if (!user) { return { redirect: { destination: '/login', permanent: false, }, } } return { props: { user }, } }) const Profile = ({ user }) => { // Показываем данные пользователя. Обработка состояния загрузки не требуется! return ( <Layout> <h1>Ваш профиль</h1> <pre>{JSON.stringify(user, null, 2)}</pre> </Layout> ) } export default Profile

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

Провайдеры аутентификации

Теперь, когда мы обсудили паттерны аутентификации, давайте рассмотрим конкретных поставщиков и рассмотрим, как они используются с Next.js.

Перенесите свою собственную базу данных пользователей

Если у вас есть существующая база данных с пользовательскими данными, вы, вероятно, захотите использовать решение с открытым исходным кодом, которое не зависит от поставщика.

  • Если вам нужна низкоуровневая, зашифрованная утилита сеанса без сохранения состояния, используйте iron-session.
  • Если вам нужна полнофункциональная система аутентификации со встроенными провайдерами (Google, Facebook, GitHub…), JWT, JWE, электронной почтой/паролем, магическими ссылками и многим другим… используйте next-auth.

Обе эти библиотеки поддерживают любой шаблон аутентификации. Если вы заинтересованы в Passport, у нас также есть примеры для него с использованием безопасных и зашифрованных файлов cookie:

Другие провайдеры:

Чтобы увидеть примеры с другими поставщиками аутентификации, проверьте папку примеров.