From a6c68cef69022092de551ad2b878e7c244911b42 Mon Sep 17 00:00:00 2001 From: wangsijie Date: Wed, 1 Jan 2025 14:59:19 +0800 Subject: [PATCH] feat: add next.js external storage --- .../framework/next-app-router/README.mdx | 5 +++ docs/quick-starts/framework/next/README.mdx | 5 +++ .../framework/next/_external-storage.mdx | 39 +++++++++++++++++++ .../framework/next-app-router/README.mdx | 5 +++ .../quick-starts/framework/next/README.mdx | 5 +++ .../framework/next/_external-storage.mdx | 39 +++++++++++++++++++ .../framework/next-app-router/README.mdx | 11 ++++-- .../quick-starts/framework/next/README.mdx | 7 +++- .../framework/next/_external-storage.mdx | 39 +++++++++++++++++++ .../framework/next-app-router/README.mdx | 16 +++++--- .../quick-starts/framework/next/README.mdx | 9 ++++- .../framework/next/_external-storage.mdx | 39 +++++++++++++++++++ .../framework/next-app-router/README.mdx | 13 +++++-- .../quick-starts/framework/next/README.mdx | 11 ++++-- .../framework/next/_external-storage.mdx | 39 +++++++++++++++++++ .../framework/next-app-router/README.mdx | 11 ++++-- .../quick-starts/framework/next/README.mdx | 9 ++++- .../framework/next/_external-storage.mdx | 39 +++++++++++++++++++ .../framework/next-app-router/README.mdx | 24 +++++++----- .../quick-starts/framework/next/README.mdx | 11 ++++-- .../framework/next/_external-storage.mdx | 39 +++++++++++++++++++ 21 files changed, 380 insertions(+), 35 deletions(-) create mode 100644 docs/quick-starts/framework/next/_external-storage.mdx create mode 100644 i18n/de/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx create mode 100644 i18n/es/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx create mode 100644 i18n/ja/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx create mode 100644 i18n/pt-BR/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx create mode 100644 i18n/zh-CN/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx diff --git a/docs/quick-starts/framework/next-app-router/README.mdx b/docs/quick-starts/framework/next-app-router/README.mdx index e09fc89fd07..9eda3669880 100644 --- a/docs/quick-starts/framework/next-app-router/README.mdx +++ b/docs/quick-starts/framework/next-app-router/README.mdx @@ -9,6 +9,7 @@ sidebar_custom_props: import ApiResourcesDescription from '../../fragments/_api-resources-description.md'; import FurtherReadings from '../../fragments/_further-readings.md'; +import ExternalStorage from '../next/_external-storage.mdx'; import Installation from '../next/_installation.mdx'; import GetUserInformation from './_get-user-information.mdx'; @@ -101,6 +102,10 @@ HTTP does not allow setting cookies after streaming starts, `getOrganizationToke ::: +## Use external session storage \{#use-external-session-storage} + + + ## Further readings \{#further-readings} diff --git a/docs/quick-starts/framework/next/README.mdx b/docs/quick-starts/framework/next/README.mdx index d6de0f876bb..61bd9b6c548 100644 --- a/docs/quick-starts/framework/next/README.mdx +++ b/docs/quick-starts/framework/next/README.mdx @@ -13,6 +13,7 @@ framework: Next.js import ApiResourcesDescription from '../../fragments/_api-resources-description.md'; import FurtherReadings from '../../fragments/_further-readings.md'; +import ExternalStorage from './_external-storage.mdx'; import GetUserInformation from './_get-user-information.mdx'; import GuideTip from './_guide-tip.mdx'; import Installation from './_installation.mdx'; @@ -96,6 +97,10 @@ export const config = { Check the [next-sample](https://github.com/logto-io/js/tree/master/packages/next-sample) to see full example. ::: +## Use external session storage \{#use-external-session-storage} + + + ## Further readings \{#further-readings} diff --git a/docs/quick-starts/framework/next/_external-storage.mdx b/docs/quick-starts/framework/next/_external-storage.mdx new file mode 100644 index 00000000000..5b15fa55774 --- /dev/null +++ b/docs/quick-starts/framework/next/_external-storage.mdx @@ -0,0 +1,39 @@ +The SDK uses cookies to store encrypted session data by default. This approach is secure, requires no additional infrastructure, and works especially well in serverless environments like Vercel. + +However, there are times when you might need to store session data externally. For instance, when your session data grows too large for cookies, especially when you need to maintain multiple active organization sessions simultaneously. In these cases, you can implement external session storage using the `sessionWrapper` option: + +```ts +import { MemorySessionWrapper } from './storage'; + +export const config = { + // ... + sessionWrapper: new MemorySessionWrapper(), +}; +``` + +```ts +import { randomUUID } from 'node:crypto'; + +import { type SessionWrapper, type SessionData } from '@logto/next'; + +export class MemorySessionWrapper implements SessionWrapper { + private readonly storage = new Map(); + + async wrap(data: unknown, _key: string): Promise { + const sessionId = randomUUID(); + this.storage.set(sessionId, data); + return sessionId; + } + + async unwrap(value: string, _key: string): Promise { + if (!value) { + return {}; + } + + const data = this.storage.get(value); + return data ?? {}; + } +} +``` + +The above implementation uses a simple in-memory storage. In a production environment, you might want to use a more persistent storage solution, such as Redis or a database. diff --git a/i18n/de/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx b/i18n/de/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx index ca0e816416c..cecfc36ed56 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx +++ b/i18n/de/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx @@ -9,6 +9,7 @@ sidebar_custom_props: import ApiResourcesDescription from '../../fragments/_api-resources-description.md'; import FurtherReadings from '../../fragments/_further-readings.md'; +import ExternalStorage from '../next/_external-storage.mdx'; import Installation from '../next/_installation.mdx'; import GetUserInformation from './_get-user-information.mdx'; @@ -101,6 +102,10 @@ HTTP erlaubt es nicht, Cookies zu setzen, nachdem das Streaming begonnen hat. `g ::: +## Externen Sitzungspeicher verwenden \{#use-external-session-storage} + + + ## Weiterführende Lektüre \{#further-readings} diff --git a/i18n/de/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx b/i18n/de/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx index 6c5177ccc8a..5e6bf30213a 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx +++ b/i18n/de/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx @@ -13,6 +13,7 @@ framework: Next.js import ApiResourcesDescription from '../../fragments/_api-resources-description.md'; import FurtherReadings from '../../fragments/_further-readings.md'; +import ExternalStorage from './_external-storage.mdx'; import GetUserInformation from './_get-user-information.mdx'; import GuideTip from './_guide-tip.mdx'; import Installation from './_installation.mdx'; @@ -96,6 +97,10 @@ export const config = { Sieh dir das [next-sample](https://github.com/logto-io/js/tree/master/packages/next-sample) an, um ein vollständiges Beispiel zu sehen. ::: +## Externen Sitzungs-Speicher verwenden \{#use-external-session-storage} + + + ## Weiterführende Lektüre \{#further-readings} diff --git a/i18n/de/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx b/i18n/de/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx new file mode 100644 index 00000000000..afdc36c1d6d --- /dev/null +++ b/i18n/de/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx @@ -0,0 +1,39 @@ +Das SDK verwendet standardmäßig Cookies, um verschlüsselte Sitzungsdaten zu speichern. Dieser Ansatz ist sicher, erfordert keine zusätzliche Infrastruktur und funktioniert besonders gut in serverlosen Umgebungen wie Vercel. + +Es gibt jedoch Zeiten, in denen du Sitzungsdaten extern speichern musst. Zum Beispiel, wenn deine Sitzungsdaten zu groß für Cookies werden, insbesondere wenn du mehrere aktive Organisation-Sitzungen gleichzeitig aufrechterhalten musst. In diesen Fällen kannst du eine externe Sitzungspeicherung mit der Option `sessionWrapper` implementieren: + +```ts +import { MemorySessionWrapper } from './storage'; + +export const config = { + // ... + sessionWrapper: new MemorySessionWrapper(), +}; +``` + +```ts +import { randomUUID } from 'node:crypto'; + +import { type SessionWrapper, type SessionData } from '@logto/next'; + +export class MemorySessionWrapper implements SessionWrapper { + private readonly storage = new Map(); + + async wrap(data: unknown, _key: string): Promise { + const sessionId = randomUUID(); + this.storage.set(sessionId, data); + return sessionId; + } + + async unwrap(value: string, _key: string): Promise { + if (!value) { + return {}; + } + + const data = this.storage.get(value); + return data ?? {}; + } +} +``` + +Die obige Implementierung verwendet einen einfachen In-Memory-Speicher. In einer Produktionsumgebung möchtest du möglicherweise eine beständigere Speicherlösung verwenden, wie Redis oder eine Datenbank. diff --git a/i18n/es/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx b/i18n/es/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx index a7505b236eb..8b5b74c109d 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx +++ b/i18n/es/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx @@ -9,6 +9,7 @@ sidebar_custom_props: import ApiResourcesDescription from '../../fragments/_api-resources-description.md'; import FurtherReadings from '../../fragments/_further-readings.md'; +import ExternalStorage from '../next/_external-storage.mdx'; import Installation from '../next/_installation.mdx'; import GetUserInformation from './_get-user-information.mdx'; @@ -43,7 +44,7 @@ import FetchOrganizationTokenForUser from './api-resources/_fetch-organization-t -### Configurar cliente Logto \{#configure-logto-client} +### Configurar el cliente de Logto \{#configure-logto-client} @@ -70,7 +71,7 @@ export default async function Home() { :::tip -HTTP no permite establecer cookies después de que comienza la transmisión, `getAccessTokenRSC` no puede actualizar el valor de la cookie, por lo que si el token de acceso se actualiza, no se conservará en la sesión. Se recomienda usar la función `getAccessToken` en el lado del cliente o en los manejadores de rutas. +HTTP no permite establecer cookies después de que comienza la transmisión, `getAccessTokenRSC` no puede actualizar el valor de la cookie, por lo que si el token de acceso se actualiza, no se persistirá en la sesión. Se recomienda usar la función `getAccessToken` en el lado del cliente o en los manejadores de rutas. ::: @@ -97,10 +98,14 @@ export default async function Home() { :::tip -HTTP no permite establecer cookies después de que comienza la transmisión, `getOrganizationTokenRSC` no puede actualizar el valor de la cookie, por lo que si el token de acceso se actualiza, no se conservará en la sesión. Se recomienda usar la función `getOrganizationToken` en el lado del cliente o en los manejadores de rutas. +HTTP no permite establecer cookies después de que comienza la transmisión, `getOrganizationTokenRSC` no puede actualizar el valor de la cookie, por lo que si el token de acceso se actualiza, no se persistirá en la sesión. Se recomienda usar la función `getOrganizationToken` en el lado del cliente o en los manejadores de rutas. ::: +## Usar almacenamiento de sesión externo \{#use-external-session-storage} + + + ## Lecturas adicionales \{#further-readings} diff --git a/i18n/es/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx b/i18n/es/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx index b219bfd2618..7c3eca54081 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx +++ b/i18n/es/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx @@ -13,6 +13,7 @@ framework: Next.js import ApiResourcesDescription from '../../fragments/_api-resources-description.md'; import FurtherReadings from '../../fragments/_further-readings.md'; +import ExternalStorage from './_external-storage.mdx'; import GetUserInformation from './_get-user-information.mdx'; import GuideTip from './_guide-tip.mdx'; import Installation from './_installation.mdx'; @@ -78,7 +79,7 @@ export const logtoClient = new LogtoClient({ }); ``` -Luego, establece el runtime en `experimental-edge` o `edge` en la ruta de la API. +Luego establece el runtime en `experimental-edge` o `edge` en la ruta de la API. ```ts title="pages/api/logto/sign-in.ts" import { logtoClient } from '../../../../libraries/logto'; @@ -96,6 +97,10 @@ export const config = { Consulta el [next-sample](https://github.com/logto-io/js/tree/master/packages/next-sample) para ver un ejemplo completo. ::: +## Usar almacenamiento de sesión externo \{#use-external-session-storage} + + + ## Lecturas adicionales \{#further-readings} diff --git a/i18n/es/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx b/i18n/es/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx new file mode 100644 index 00000000000..bbbbdb6d4b4 --- /dev/null +++ b/i18n/es/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx @@ -0,0 +1,39 @@ +El SDK utiliza cookies para almacenar datos de sesión cifrados por defecto. Este enfoque es seguro, no requiere infraestructura adicional y funciona especialmente bien en entornos sin servidor como Vercel. + +Sin embargo, hay ocasiones en las que podrías necesitar almacenar los datos de sesión externamente. Por ejemplo, cuando tus datos de sesión crecen demasiado para las cookies, especialmente cuando necesitas mantener múltiples sesiones activas de organización simultáneamente. En estos casos, puedes implementar un almacenamiento de sesión externo utilizando la opción `sessionWrapper`: + +```ts +import { MemorySessionWrapper } from './storage'; + +export const config = { + // ... + sessionWrapper: new MemorySessionWrapper(), +}; +``` + +```ts +import { randomUUID } from 'node:crypto'; + +import { type SessionWrapper, type SessionData } from '@logto/next'; + +export class MemorySessionWrapper implements SessionWrapper { + private readonly storage = new Map(); + + async wrap(data: unknown, _key: string): Promise { + const sessionId = randomUUID(); + this.storage.set(sessionId, data); + return sessionId; + } + + async unwrap(value: string, _key: string): Promise { + if (!value) { + return {}; + } + + const data = this.storage.get(value); + return data ?? {}; + } +} +``` + +La implementación anterior utiliza un almacenamiento en memoria simple. En un entorno de producción, podrías querer usar una solución de almacenamiento más persistente, como Redis o una base de datos. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx b/i18n/fr/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx index 9e9987f0078..ff57251717d 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx +++ b/i18n/fr/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx @@ -3,11 +3,13 @@ slug: /quick-starts/next-app-router sidebar_label: Next.js (App Router) sidebar_custom_props: logoFilename: 'next.svg' + darkLogoFilename: 'next-dark.svg' description: Next.js App Router est un nouveau paradigme pour construire des applications en utilisant les dernières fonctionnalités de React. --- import ApiResourcesDescription from '../../fragments/_api-resources-description.md'; import FurtherReadings from '../../fragments/_further-readings.md'; +import ExternalStorage from '../next/_external-storage.mdx'; import Installation from '../next/_installation.mdx'; import GetUserInformation from './_get-user-information.mdx'; @@ -34,7 +36,7 @@ import FetchOrganizationTokenForUser from './api-resources/_fetch-organization-t -## Récupérer les informations de l'utilisateur \{#fetch-user-information} +## Récupérer les informations utilisateur \{#fetch-user-information} @@ -46,7 +48,7 @@ import FetchOrganizationTokenForUser from './api-resources/_fetch-organization-t -### Récupérer un jeton d’accès pour la ressource API \{#fetch-access-token-for-the-api-resource} +### Récupérer le jeton d’accès pour la ressource API \{#fetch-access-token-for-the-api-resource} @@ -61,7 +63,7 @@ export default async function Home() { return (
-

Access token: {accessToken}

+

Jeton d’accès : {accessToken}

); } @@ -73,7 +75,7 @@ HTTP ne permet pas de définir des cookies après le début du streaming, `getAc ::: -### Récupérer des jetons d’organisation \{#fetch-organization-tokens} +### Récupérer les jetons d’organisation \{#fetch-organization-tokens} @@ -88,7 +90,7 @@ export default async function Home() { return (
-

Organization token: {token}

+

Jeton d’organisation : {token}

); } @@ -100,6 +102,10 @@ HTTP ne permet pas de définir des cookies après le début du streaming, `getOr ::: +## Utiliser un stockage de session externe \{#use-external-session-storage} + + + ## Lectures complémentaires \{#further-readings} diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx b/i18n/fr/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx index 89e129c90df..2b008765198 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx +++ b/i18n/fr/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx @@ -13,6 +13,7 @@ framework: Next.js import ApiResourcesDescription from '../../fragments/_api-resources-description.md'; import FurtherReadings from '../../fragments/_further-readings.md'; +import ExternalStorage from './_external-storage.mdx'; import GetUserInformation from './_get-user-information.mdx'; import GuideTip from './_guide-tip.mdx'; import Installation from './_installation.mdx'; @@ -70,8 +71,8 @@ import LogtoClient from '@logto/next/edge'; export const logtoClient = new LogtoClient({ appId: '', appSecret: '', - endpoint: '', // Par exemple http://localhost:3001 - baseUrl: '', // Par exemple http://localhost:3000 + endpoint: '', // Par exemple, http://localhost:3001 + baseUrl: '', // Par exemple, http://localhost:3000 cookieSecret: 'complex_password_at_least_32_characters_long', cookieSecure: process.env.NODE_ENV === 'production', resources: [''], @@ -96,6 +97,10 @@ export const config = { Consultez le [next-sample](https://github.com/logto-io/js/tree/master/packages/next-sample) pour voir un exemple complet. ::: +## Utiliser un stockage de session externe \{#use-external-session-storage} + + + ## Lectures complémentaires \{#further-readings} diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx b/i18n/fr/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx new file mode 100644 index 00000000000..36b0dd014d0 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx @@ -0,0 +1,39 @@ +Le SDK utilise des cookies pour stocker les données de session chiffrées par défaut. Cette approche est sécurisée, ne nécessite pas d'infrastructure supplémentaire et fonctionne particulièrement bien dans des environnements sans serveur comme Vercel. + +Cependant, il y a des moments où vous pourriez avoir besoin de stocker les données de session de manière externe. Par exemple, lorsque vos données de session deviennent trop volumineuses pour les cookies, surtout lorsque vous devez maintenir plusieurs sessions d'organisation actives simultanément. Dans ces cas, vous pouvez implémenter un stockage de session externe en utilisant l'option `sessionWrapper` : + +```ts +import { MemorySessionWrapper } from './storage'; + +export const config = { + // ... + sessionWrapper: new MemorySessionWrapper(), +}; +``` + +```ts +import { randomUUID } from 'node:crypto'; + +import { type SessionWrapper, type SessionData } from '@logto/next'; + +export class MemorySessionWrapper implements SessionWrapper { + private readonly storage = new Map(); + + async wrap(data: unknown, _key: string): Promise { + const sessionId = randomUUID(); + this.storage.set(sessionId, data); + return sessionId; + } + + async unwrap(value: string, _key: string): Promise { + if (!value) { + return {}; + } + + const data = this.storage.get(value); + return data ?? {}; + } +} +``` + +L'implémentation ci-dessus utilise un simple stockage en mémoire. Dans un environnement de production, vous pourriez vouloir utiliser une solution de stockage plus persistante, comme Redis ou une base de données. diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx b/i18n/ja/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx index 6a4fccc266f..be8339c4b22 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx +++ b/i18n/ja/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx @@ -9,6 +9,7 @@ sidebar_custom_props: import ApiResourcesDescription from '../../fragments/_api-resources-description.md'; import FurtherReadings from '../../fragments/_further-readings.md'; +import ExternalStorage from '../next/_external-storage.mdx'; import Installation from '../next/_installation.mdx'; import GetUserInformation from './_get-user-information.mdx'; @@ -25,7 +26,7 @@ import FetchOrganizationTokenForUser from './api-resources/_fetch-organization-t ## 前提条件 \{#prerequisites} - [Logto Cloud](https://cloud.logto.io) アカウントまたは [セルフホスト Logto](/introduction/set-up-logto-oss)。 -- 作成された Logto の従来のアプリケーション。 +- Logto の従来のアプリケーションが作成されていること。 ## インストール \{#installation} @@ -47,7 +48,7 @@ import FetchOrganizationTokenForUser from './api-resources/_fetch-organization-t -### API リソースのアクセス トークンを取得する \{#fetch-access-token-for-the-api-resource} +### API リソースのアクセス トークンの取得 \{#fetch-access-token-for-the-api-resource} @@ -70,7 +71,7 @@ export default async function Home() { :::tip -HTTP はストリーミングが開始された後にクッキーを設定することを許可していないため、`getAccessTokenRSC` はクッキーの値を更新できません。そのため、アクセス トークンが更新されてもセッションに保持されません。クライアント側またはルートハンドラーで `getAccessToken` 関数を使用することをお勧めします。 +HTTP はストリーミングが開始された後にクッキーを設定することを許可していないため、`getAccessTokenRSC` はクッキーの値を更新できません。そのため、アクセス トークンが更新されても、セッションに保存されません。クライアント側またはルートハンドラーで `getAccessToken` 関数を使用することをお勧めします。 ::: @@ -97,10 +98,14 @@ export default async function Home() { :::tip -HTTP はストリーミングが開始された後にクッキーを設定することを許可していないため、`getOrganizationTokenRSC` はクッキーの値を更新できません。そのため、アクセス トークンが更新されてもセッションに保持されません。クライアント側またはルートハンドラーで `getOrganizationToken` 関数を使用することをお勧めします。 +HTTP はストリーミングが開始された後にクッキーを設定することを許可していないため、`getOrganizationTokenRSC` はクッキーの値を更新できません。そのため、アクセス トークンが更新されても、セッションに保存されません。クライアント側またはルートハンドラーで `getOrganizationToken` 関数を使用することをお勧めします。 ::: +## 外部セッションストレージの使用 \{#use-external-session-storage} + + + ## さらなる読み物 \{#further-readings} diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx b/i18n/ja/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx index c3115cc0025..b63c74f14ed 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx +++ b/i18n/ja/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx @@ -3,16 +3,17 @@ slug: /quick-starts/next sidebar_label: Next.js (Pages Router) sidebar_custom_props: darkLogoFilename: 'next-dark.svg' - description: Next.js は本番環境向けの React フレームワークで、フルスタック React アプリの構築を簡単にし、組み込みの SSR を備えています。 + description: Next.js はプロダクション向けの React フレームワークで、フルスタックの React アプリを簡単に構築でき、組み込みの SSR を備えています。 language: js official_link: https://nextjs.org -app_type: 従来のウェブ +app_type: Traditional web framework: Next.js --- import ApiResourcesDescription from '../../fragments/_api-resources-description.md'; import FurtherReadings from '../../fragments/_further-readings.md'; +import ExternalStorage from './_external-storage.mdx'; import GetUserInformation from './_get-user-information.mdx'; import GuideTip from './_guide-tip.mdx'; import Installation from './_installation.mdx'; @@ -28,7 +29,7 @@ import FetchOrganizationTokenForUser from './api-resources/_fetch-organization-t ## 前提条件 \{#prerequisites} - [Logto Cloud](https://cloud.logto.io) アカウントまたは [セルフホスト Logto](/introduction/set-up-logto-oss)。 -- 作成された Logto 従来のアプリケーション。 +- 作成された Logto の従来のアプリケーション。 ## インストール \{#installation} @@ -96,6 +97,10 @@ export const config = { 完全な例を見るには、[next-sample](https://github.com/logto-io/js/tree/master/packages/next-sample) を確認してください。 ::: +## 外部セッションストレージを使用する \{#use-external-session-storage} + + + ## さらなる読み物 \{#further-readings} diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx b/i18n/ja/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx new file mode 100644 index 00000000000..04063a7eed3 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx @@ -0,0 +1,39 @@ +SDK はデフォルトでクッキーを使用して暗号化されたセッションデータを保存します。このアプローチは安全で、追加のインフラストラクチャを必要とせず、特に Vercel のようなサーバーレス環境でうまく機能します。 + +しかし、セッションデータを外部に保存する必要がある場合もあります。たとえば、セッションデータがクッキーに収まりきらないほど大きくなった場合や、複数のアクティブな組織セッションを同時に維持する必要がある場合です。このような場合、`sessionWrapper` オプションを使用して外部セッションストレージを実装できます: + +```ts +import { MemorySessionWrapper } from './storage'; + +export const config = { + // ... + sessionWrapper: new MemorySessionWrapper(), +}; +``` + +```ts +import { randomUUID } from 'node:crypto'; + +import { type SessionWrapper, type SessionData } from '@logto/next'; + +export class MemorySessionWrapper implements SessionWrapper { + private readonly storage = new Map(); + + async wrap(data: unknown, _key: string): Promise { + const sessionId = randomUUID(); + this.storage.set(sessionId, data); + return sessionId; + } + + async unwrap(value: string, _key: string): Promise { + if (!value) { + return {}; + } + + const data = this.storage.get(value); + return data ?? {}; + } +} +``` + +上記の実装は、シンプルなインメモリストレージを使用しています。本番環境では、Redis やデータベースなど、より永続的なストレージソリューションを使用することをお勧めします。 diff --git a/i18n/pt-BR/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx b/i18n/pt-BR/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx index e18a1c1db46..8245582cd13 100644 --- a/i18n/pt-BR/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx +++ b/i18n/pt-BR/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx @@ -4,11 +4,12 @@ sidebar_label: Next.js (App Router) sidebar_custom_props: logoFilename: 'next.svg' darkLogoFilename: 'next-dark.svg' - description: Next.js App Router é um novo paradigma para construir aplicativos usando os recursos mais recentes do React. + description: Next.js App Router é um novo paradigma para construir aplicações usando os recursos mais recentes do React. --- import ApiResourcesDescription from '../../fragments/_api-resources-description.md'; import FurtherReadings from '../../fragments/_further-readings.md'; +import ExternalStorage from '../next/_external-storage.mdx'; import Installation from '../next/_installation.mdx'; import GetUserInformation from './_get-user-information.mdx'; @@ -70,7 +71,7 @@ export default async function Home() { :::tip -O HTTP não permite definir cookies após o início do streaming, `getAccessTokenRSC` não pode atualizar o valor do cookie, então se o token de acesso for atualizado, ele não será persistido na sessão. Recomenda-se usar a função `getAccessToken` no lado do cliente ou em manipuladores de rota. +O HTTP não permite definir cookies após o início do streaming, `getAccessTokenRSC` não pode atualizar o valor do cookie, então se o token de acesso for atualizado, ele não será persistido na sessão. Recomenda-se usar a função `getAccessToken` no lado do cliente ou em manipuladores de rotas. ::: @@ -97,10 +98,14 @@ export default async function Home() { :::tip -O HTTP não permite definir cookies após o início do streaming, `getOrganizationTokenRSC` não pode atualizar o valor do cookie, então se o token de acesso for atualizado, ele não será persistido na sessão. Recomenda-se usar a função `getOrganizationToken` no lado do cliente ou em manipuladores de rota. +O HTTP não permite definir cookies após o início do streaming, `getOrganizationTokenRSC` não pode atualizar o valor do cookie, então se o token de acesso for atualizado, ele não será persistido na sessão. Recomenda-se usar a função `getOrganizationToken` no lado do cliente ou em manipuladores de rotas. ::: +## Usar armazenamento de sessão externo \{#use-external-session-storage} + + + ## Leituras adicionais \{#further-readings} diff --git a/i18n/pt-BR/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx b/i18n/pt-BR/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx index e3692caa187..aa28ab62c14 100644 --- a/i18n/pt-BR/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx +++ b/i18n/pt-BR/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx @@ -6,13 +6,14 @@ sidebar_custom_props: description: Next.js é um framework React para produção - facilita a construção de aplicativos React fullstack e vem com SSR embutido. language: js official_link: https://nextjs.org -app_type: Aplicativo web tradicional +app_type: Traditional web framework: Next.js --- import ApiResourcesDescription from '../../fragments/_api-resources-description.md'; import FurtherReadings from '../../fragments/_further-readings.md'; +import ExternalStorage from './_external-storage.mdx'; import GetUserInformation from './_get-user-information.mdx'; import GuideTip from './_guide-tip.mdx'; import Installation from './_installation.mdx'; @@ -72,7 +73,7 @@ export const logtoClient = new LogtoClient({ appSecret: '', endpoint: '', // Ex.: http://localhost:3001 baseUrl: '', // Ex.: http://localhost:3000 - cookieSecret: 'senha_complexa_com_pelo_menos_32_caracteres', + cookieSecret: 'complex_password_at_least_32_characters_long', cookieSecure: process.env.NODE_ENV === 'production', resources: [''], }); @@ -96,6 +97,10 @@ export const config = { Confira o [next-sample](https://github.com/logto-io/js/tree/master/packages/next-sample) para ver um exemplo completo. ::: +## Usar armazenamento de sessão externo \{#use-external-session-storage} + + + ## Leituras adicionais \{#further-readings} diff --git a/i18n/pt-BR/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx b/i18n/pt-BR/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx new file mode 100644 index 00000000000..6b99589a4d1 --- /dev/null +++ b/i18n/pt-BR/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx @@ -0,0 +1,39 @@ +O SDK usa cookies para armazenar dados de sessão criptografados por padrão. Essa abordagem é segura, não requer infraestrutura adicional e funciona especialmente bem em ambientes serverless como o Vercel. + +No entanto, há momentos em que você pode precisar armazenar dados de sessão externamente. Por exemplo, quando seus dados de sessão crescem muito para os cookies, especialmente quando você precisa manter várias sessões ativas de organização simultaneamente. Nesses casos, você pode implementar o armazenamento de sessão externo usando a opção `sessionWrapper`: + +```ts +import { MemorySessionWrapper } from './storage'; + +export const config = { + // ... + sessionWrapper: new MemorySessionWrapper(), +}; +``` + +```ts +import { randomUUID } from 'node:crypto'; + +import { type SessionWrapper, type SessionData } from '@logto/next'; + +export class MemorySessionWrapper implements SessionWrapper { + private readonly storage = new Map(); + + async wrap(data: unknown, _key: string): Promise { + const sessionId = randomUUID(); + this.storage.set(sessionId, data); + return sessionId; + } + + async unwrap(value: string, _key: string): Promise { + if (!value) { + return {}; + } + + const data = this.storage.get(value); + return data ?? {}; + } +} +``` + +A implementação acima usa um armazenamento simples em memória. Em um ambiente de produção, você pode querer usar uma solução de armazenamento mais persistente, como Redis ou um banco de dados. diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx b/i18n/zh-CN/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx index 4a00ec49655..7a936f4955c 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/quick-starts/framework/next-app-router/README.mdx @@ -3,11 +3,13 @@ slug: /quick-starts/next-app-router sidebar_label: Next.js (App Router) sidebar_custom_props: logoFilename: 'next.svg' + darkLogoFilename: 'next-dark.svg' description: Next.js App Router 是一种使用 React 最新特性构建应用的新范式。 --- import ApiResourcesDescription from '../../fragments/_api-resources-description.md'; import FurtherReadings from '../../fragments/_further-readings.md'; +import ExternalStorage from '../next/_external-storage.mdx'; import Installation from '../next/_installation.mdx'; import GetUserInformation from './_get-user-information.mdx'; @@ -24,7 +26,7 @@ import FetchOrganizationTokenForUser from './api-resources/_fetch-organization-t ## 前提条件 \{#prerequisites} - 一个 [Logto Cloud](https://cloud.logto.io) 账户或一个 [自托管 Logto](/introduction/set-up-logto-oss)。 -- 一个 Logto 传统应用已创建。 +- 一个已创建的 Logto 传统应用。 ## 安装 \{#installation} @@ -46,11 +48,11 @@ import FetchOrganizationTokenForUser from './api-resources/_fetch-organization-t -### 获取 API 资源的访问令牌 (Access token) \{#fetch-access-token-for-the-api-resource} +### 获取 API 资源的访问令牌 \{#fetch-access-token-for-the-api-resource} -如果你需要在服务器组件中获取访问令牌 (Access token),可以使用 `getAccessTokenRSC` 函数: +如果你需要在服务器组件中获取访问令牌,可以使用 `getAccessTokenRSC` 函数: ```tsx title="app/page.tsx" import { getAccessTokenRSC } from '@logto/next/server-actions'; @@ -61,7 +63,7 @@ export default async function Home() { return (
-

Access token: {accessToken}

+

访问令牌: {accessToken}

); } @@ -69,15 +71,15 @@ export default async function Home() { :::tip -HTTP 不允许在流开始后设置 cookie,`getAccessTokenRSC` 无法更新 cookie 值,因此如果访问令牌 (Access token) 被刷新,它将不会在会话中持久化。建议在客户端或路由处理程序中使用 `getAccessToken` 函数。 +HTTP 不允许在流开始后设置 cookie,`getAccessTokenRSC` 无法更新 cookie 值,因此如果访问令牌被刷新,它将不会在会话中持久化。建议在客户端或路由处理程序中使用 `getAccessToken` 函数。 ::: -### 获取组织令牌 (Organization tokens) \{#fetch-organization-tokens} +### 获取组织令牌 \{#fetch-organization-tokens} -如果你需要在服务器组件中获取组织令牌 (Organization token),可以使用 `getOrganizationTokenRSC` 函数: +如果你需要在服务器组件中获取组织令牌,可以使用 `getOrganizationTokenRSC` 函数: ```tsx title="app/page.tsx" import { getOrganizationTokenRSC } from '@logto/next/server-actions'; @@ -88,7 +90,7 @@ export default async function Home() { return (
-

Organization token: {token}

+

组织令牌: {token}

); } @@ -96,10 +98,14 @@ export default async function Home() { :::tip -HTTP 不允许在流开始后设置 cookie,`getOrganizationTokenRSC` 无法更新 cookie 值,因此如果访问令牌 (Access token) 被刷新,它将不会在会话中持久化。建议在客户端或路由处理程序中使用 `getOrganizationToken` 函数。 +HTTP 不允许在流开始后设置 cookie,`getOrganizationTokenRSC` 无法更新 cookie 值,因此如果访问令牌被刷新,它将不会在会话中持久化。建议在客户端或路由处理程序中使用 `getOrganizationToken` 函数。 ::: +## 使用外部会话存储 \{#use-external-session-storage} + + + ## 延伸阅读 \{#further-readings} diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx b/i18n/zh-CN/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx index df136e0c403..d60cfe71ef6 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/quick-starts/framework/next/README.mdx @@ -6,13 +6,14 @@ sidebar_custom_props: description: Next.js 是一个用于生产环境的 React 框架 - 它使构建全栈 React 应用变得轻而易举,并且内置了 SSR。 language: js official_link: https://nextjs.org -app_type: 传统 Web +app_type: 传统网页 framework: Next.js --- import ApiResourcesDescription from '../../fragments/_api-resources-description.md'; import FurtherReadings from '../../fragments/_further-readings.md'; +import ExternalStorage from './_external-storage.mdx'; import GetUserInformation from './_get-user-information.mdx'; import GuideTip from './_guide-tip.mdx'; import Installation from './_installation.mdx'; @@ -60,7 +61,7 @@ import FetchOrganizationTokenForUser from './api-resources/_fetch-organization-t ## 边缘运行时 \{#edge-runtime} -_添加于 `@logto/next@2.1.0`_ +_在 `@logto/next@2.1.0` 中添加_ 如果你想使用 [边缘运行时](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes) API 路由,你需要使用子包 `@logto/next/edge`。 @@ -96,6 +97,10 @@ export const config = { 查看 [next-sample](https://github.com/logto-io/js/tree/master/packages/next-sample) 以获取完整示例。 ::: -## 进一步阅读 \{#further-readings} +## 使用外部会话存储 \{#use-external-session-storage} + + + +## 延伸阅读 \{#further-readings} diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx b/i18n/zh-CN/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx new file mode 100644 index 00000000000..c6dfa55a6c9 --- /dev/null +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/quick-starts/framework/next/_external-storage.mdx @@ -0,0 +1,39 @@ +SDK 默认使用 cookies 存储加密的会话数据。这种方法安全、无需额外的基础设施,并且在像 Vercel 这样的无服务器环境中特别有效。 + +然而,有时你可能需要将会话数据存储在外部。例如,当你的会话数据对于 cookies 来说过大时,尤其是当你需要同时维护多个活跃的组织 (Organization) 会话时。在这些情况下,你可以使用 `sessionWrapper` 选项实现外部会话存储: + +```ts +import { MemorySessionWrapper } from './storage'; + +export const config = { + // ... + sessionWrapper: new MemorySessionWrapper(), +}; +``` + +```ts +import { randomUUID } from 'node:crypto'; + +import { type SessionWrapper, type SessionData } from '@logto/next'; + +export class MemorySessionWrapper implements SessionWrapper { + private readonly storage = new Map(); + + async wrap(data: unknown, _key: string): Promise { + const sessionId = randomUUID(); + this.storage.set(sessionId, data); + return sessionId; + } + + async unwrap(value: string, _key: string): Promise { + if (!value) { + return {}; + } + + const data = this.storage.get(value); + return data ?? {}; + } +} +``` + +上述实现使用了一个简单的内存存储。在生产环境中,你可能希望使用更持久的存储解决方案,例如 Redis 或数据库。