Давайте предположим следующий сценарий: вы создали приложение Next.js с помощью нового маршрутизатора приложений, и вам необходимо хранить конфиденциальные данные сеанса пользователя, такие как токен доступа, токен обновления или, возможно, просто формировать данные, к которым вы хотите получить доступ через веб-приложение.
Вы можете использовать встроенную динамическую функцию cookies() для хранения этих данных в файлах cookie клиента, но проблема с использованием файлов cookie заключается в том, что они хранятся на стороне клиента и уязвимы для межсайтового скриптинга (XSS). , поэтому для конфиденциальных данных, таких как токены доступа, это не идеально.
Решение
Чтобы решить эту проблему, вы можете использовать сеансы на стороне сервера для безопасного хранения ваших данных. Вы можете использовать временный кеш памяти или службу структуры хранения данных, такую как Redis, PostgreSQL, Dynamodb…. или другие.
С устаревшим маршрутизатором Page этого можно было добиться с помощью таких пакетов, как next-session, iron-session или express-session, но на момент написания этого руководства маршрутизатор приложений еще не поддерживался их.
Поэтому я написал пакет next-app-session, который работает с обработчиками маршрутов маршрутизатора приложений, серверными компонентами и серверными действиями. кроме того, он также поддерживает маршрутизатор страницы и промежуточное программное обеспечение.
https://www.npmjs.com/package/next-app-session
Как это работает
Прежде чем мы перейдем к тому, как использовать пакет, возможно, стоит описать, как он работает:
- Для новых пользователей/посетителей создается уникальный идентификатор сеанса пользователя. (ИДС)
- Этот SID будет храниться в файле cookie браузера клиента.
- При сохранении данных для пользователя его значение SID используется в качестве ключа для хранения этих данных в хранилище данных сервера, и эти данные будут связаны только с этим SID.
- Любой запрос на чтение данных сеанса сначала извлекает SID из пользовательских файлов cookie, а затем получает связанные данные из хранилища данных.
Выполнение
В этом руководстве мы будем использовать Redis в качестве хранилища данных. Если вы хотите использовать другие хранилища, этот пакет должен работать с любым пакетом экспресс-хранилища сеансов, если они передаются через promisifyStore
служебную функцию.
Итак, давайте сначала настроим наш экземпляр хранилища Redis с помощью докера. Если у вас уже есть экземпляр Redis, вы можете пропустить эти шаги.
Настройка экземпляра магазина Redis
- Обновите/создайте файл
docker-compose.yml
, чтобы иметь службу Redis (убедитесь, что вы используете неиспользуемый локальный порт)
version: '3.8' services: redis: image: redis:latest ports: - '6379:6379'
2. Запустите док-контейнер, в терминале перейдите к своему проекту и запустите: docker-compose up
Установить пакет сеанса следующего приложения
- Сначала вам нужно установить пакет вместе с пакетами Redis.
npm i next-app-session ioredis connect-redis
- Создайте файл инициализации, для этого примера мы создадим этот файл
lib/session.ts
и добавим следующий код:
import nextAppSession, {promisifyStore} from 'next-app-session'; import Redis from 'ioredis'; import RedisStoreFactory from 'connect-redis'; // Your session data type type MySessionData = { access_token?: string; refresh_token?: string; counter?: number; } export const session = nextAppSession<MySessionData>({ name: 'EXAMPLE_SID', // The cookie name that will hold sid secret: 'secret goes here' , // Providing a secret will sign the SID before storing it in the cookie, providing extra security // Assign Redis store with connection details store: promisifyStore( new RedisStore({ client: new Redis({ // The redis instance connection details host: 'localhost', port: 6379 }), prefix: 'exampleapp:' // having a prefix is optional but can be usefull if redis service is used by multiple applications }) ) });
Использование
Теперь, когда у вас настроены пакеты, вы можете начать использовать функцию session()
.
Важно: теперь вы можете использовать session()
только для Чтения данных сеанса в Компонентах сервера или Чтения и записи данных в Обработчиках маршрутов и Действия сервера. Она следует тем же правилам использования, что и динамическая функция cookie().
Пример обработчика маршрута:
// Example for route handler import { session } from '../lib/session'; //We import it from the initialisation file we created earlier // Increment counter export async function POST(request: Request) { // Read counter value froms session const current = await session().get('counter'); //Increment value or assign 1 if no value exists const newValue = current ? Number(current) + 1 : 1; // Update counter session await session().set('counter', newValue); }
Подробнее о настройке и использовании пакета можно узнать в README.file проекта