セッション
セッションはウェブサイトの重要な要素であり、特にサーバーサイドのフォーム検証やページ上でJavaScriptが利用できない場合に、サーバーが同じ人物からのリクエストを識別できるようにします。セッションは、ソーシャル、eコマース、ビジネス、教育ウェブサイトなど、ユーザーが「ログイン」できる多くのサイトの基本的な構成要素です。
Remixでは、セッションは(expressミドルウェアのようなものではなく)SessionStorage
インターフェースを実装する「セッションストレージ」オブジェクトを使用して、loader
およびaction
メソッドでルートごとに管理されます。セッションストレージは、クッキーを解析および生成する方法、およびセッションデータをデータベースまたはファイルシステムに保存する方法を理解しています。
Remixには、一般的なシナリオに対応するいくつかの事前構築済みのセッションストレージオプションと、独自のセッションストレージを作成するためのオプションが用意されています。
createCookieSessionStorage
createMemorySessionStorage
createFileSessionStorage
(node)
createWorkersKVSessionStorage
(Cloudflare Workers)
createArcTableSessionStorage
(architect, Amazon DynamoDB)
createSessionStorage
を使用したカスタムストレージ
セッションの使用
これは、クッキーセッションストレージの例です。
セッションストレージオブジェクトは app/sessions.ts
に設定することをお勧めします。これにより、セッションデータにアクセスする必要があるすべてのルートが同じ場所からインポートできます(ルートモジュールの制約も参照してください)。
セッションストレージオブジェクトへの入出力は HTTP クッキーです。getSession()
は、受信リクエストの Cookie
ヘッダーから現在のセッションを取得し、commitSession()
/destroySession()
は、送信レスポンスの Set-Cookie
ヘッダーを提供します。
loader
および action
関数でセッションにアクセスするためのメソッドを使用します。
ログインフォームは次のようになります。
そして、ログアウトフォームは次のようになります。
ログアウト(またはその他の変更)は、loader
ではなく action
で実行することが重要です。そうしないと、ユーザーがクロスサイトリクエストフォージェリ攻撃にさらされる可能性があります。また、Remix は actions
が呼び出された場合にのみ loaders
を再呼び出しします。
セッションの落とし穴
ネストされたルートのため、1つのページを構成するために複数のローダーが呼び出されることがあります。session.flash()
や session.unset()
を使用する場合、リクエスト内の他のローダーがそれを読み取ろうとしないことを確認する必要があります。そうしないと、競合状態が発生します。通常、フラッシュを使用する場合は、1つのローダーにそれを読み取らせるようにします。別のローダーがフラッシュメッセージを必要とする場合は、そのローダーに別のキーを使用してください。
createSession
TODO:
isSession
オブジェクトがRemixセッションである場合にtrue
を返します。
createSessionStorage
Remixでは、必要に応じて独自のデータベースにセッションを簡単に保存できます。createSessionStorage()
APIには、cookie
(cookieの作成オプションについてはcookiesを参照)と、セッションデータを管理するための作成、読み取り、更新、削除(CRUD)メソッドのセットが必要です。cookieはセッションIDを永続化するために使用されます。
createData
は、cookieにセッションIDが存在しない初期セッション作成時にcommitSession
から呼び出されます。
readData
は、cookieにセッションIDが存在する場合にgetSession
から呼び出されます。
updateData
は、cookieにセッションIDが既に存在する場合にcommitSession
から呼び出されます。
deleteData
はdestroySession
から呼び出されます。
次の例は、汎用的なデータベースクライアントを使用してこれをどのように行うかを示しています。
そして、次のように使用できます。
createData
とupdateData
へのexpires
引数は、cookie自体が期限切れになり、無効になる同じDate
です。この情報を使用して、データベースからセッションレコードを自動的に削除してスペースを節約したり、古い期限切れのcookieに対してデータが返されないようにしたりできます。
createCookieSessionStorage
純粋にクッキーベースのセッション(セッションデータ自体がブラウザとのセッションクッキーに保存される場合、cookiesを参照)には、createCookieSessionStorage()
を使用できます。
クッキーセッションストレージの主な利点は、使用するために追加のバックエンドサービスやデータベースが不要なことです。また、一部のロードバランシングシナリオでも有益です。ただし、クッキーベースのセッションは、ブラウザの最大許容クッキー長(通常は4kb)を超えることはできません。
欠点は、ほぼすべてのローダーとアクションでcommitSession
を実行する必要があることです。ローダーまたはアクションがセッションを少しでも変更した場合、コミットする必要があります。つまり、アクションでsession.flash
を実行し、別の場所でsession.get
を実行する場合、フラッシュされたメッセージを消すためにコミットする必要があります。他のセッションストレージ戦略では、作成時にのみコミットする必要があります(ブラウザのクッキーはセッションデータを保存せず、他の場所でそれを見つけるためのキーのみを保存するため、変更する必要はありません)。
他のセッション実装では、クッキーに一意のセッションIDを保存し、そのIDを使用して真実のソース(インメモリ、ファイルシステム、DBなど)でセッションを検索することに注意してください。クッキーセッションでは、クッキーが真実のソースであるため、すぐに使用できる一意のIDはありません。クッキーセッションで一意のIDを追跡する必要がある場合は、session.set()
を使用してID値を自分で追加する必要があります。
createMemorySessionStorage
このストレージは、すべてのクッキー情報をサーバーのメモリに保持します。
これは開発環境でのみ使用してください。本番環境では他のいずれかの方法を使用してください。
createFileSessionStorage
(node)
ファイルベースのセッションには、createFileSessionStorage()
を使用します。ファイルセッションストレージにはファイルシステムが必要ですが、これは express を実行するほとんどのクラウドプロバイダーで、おそらくいくつかの追加設定で容易に利用できるはずです。
ファイルベースのセッションの利点は、セッションIDのみがクッキーに保存され、残りのデータはディスク上の通常のファイルに保存されることです。これは、4kbを超えるデータを持つセッションに最適です。
サーバーレス関数にデプロイする場合は、永続的なファイルシステムへのアクセスがあることを確認してください。通常、追加の設定なしではファイルシステムは利用できません。
createWorkersKVSessionStorage
(Cloudflare Workers)
Cloudflare Workers KV をバックエンドとしたセッションには、createWorkersKVSessionStorage()
を使用します。
KV をバックエンドとしたセッションの利点は、セッション ID のみが Cookie に保存され、残りのデータはグローバルに複製された、低レイテンシーのデータストアに、非常に高い読み取りボリュームと低レイテンシーで保存されることです。
createArcTableSessionStorage
(architect, Amazon DynamoDB)
Amazon DynamoDB をバックエンドとするセッションには、createArcTableSessionStorage()
を使用します。
DynamoDB をバックエンドとするセッションの利点は、セッション ID のみが Cookie に保存され、残りのデータはグローバルにレプリケートされ、低レイテンシーで、非常に高い読み取りボリュームを低レイテンシーで処理できるデータストアに保存されることです。
# app.arc
sessions
_idx *String
_ttl TTL
セッション API
getSession
でセッションを取得した後、返されるセッションオブジェクトにはいくつかのメソッドとプロパティがあります。
session.has(key)
指定された name
を持つ変数がセッションにある場合は true
を返します。
session.set(key, value)
後続のリクエストで使用するためのセッション値を設定します。
session.flash(key, value)
セッション値を設定します。この値は最初に読み込まれたときに削除されます。その後は、なくなります。「フラッシュメッセージ」やサーバーサイドのフォーム検証メッセージに最も役立ちます。
これで、ローダーでメッセージを読み取ることができます。
flash
を読み取るたびにセッションをコミットする必要があります。これは、一部のミドルウェアが自動的に Cookie ヘッダーを設定してくれる場合とは異なり、慣れているものとは異なるかもしれません。
session.get()
以前のリクエストからセッション値にアクセスします。
session.unset()
セッションから値を削除します。
cookieSessionStorageを使用している場合、unset
するたびにセッションをコミットする必要があります。