Skip to content
Server Plugin

セッション

必須依存関係: io.ktor:ktor-server-sessions

コード例: session-cookie-client, session-cookie-server, session-header-server

ネイティブサーバー
KtorはKotlin/Nativeをサポートしており、追加のランタイムや仮想マシンなしでサーバーを実行できます。
のサポート: ✅

[Sessions](https://api.ktor.io/ktor-server/ktor-server-plugins/ktor-server-sessions/io.ktor.server.sessions/-sessions.html)プラグインは、異なるHTTPリクエスト間でデータを永続化するメカニズムを提供します。一般的な使用例としては、ログイン中のユーザーIDの保存、ショッピングカートの内容、またはクライアント上でのユーザー設定の保持などがあります。Ktorでは、Cookieまたはカスタムヘッダーを使用してセッションを実装し、セッションデータをサーバーに保存するかクライアントに渡すかを選択したり、セッションデータを署名・暗号化したりすることができます。

このトピックでは、Sessionsプラグインのインストール方法、構成方法、およびルートハンドラー内でのセッションデータへのアクセス方法について説明します。

依存関係の追加

セッションのサポートを有効にするには、ビルドスクリプトにktor-server-sessionsアーティファクトを含める必要があります。

Kotlin
Groovy
XML

セッションのインストール

アプリケーションにSessionsプラグインをインストールするには、 指定された

モジュール
モジュールを使用すると、ルートをグループ化してアプリケーションを構造化できます。
内のinstall関数に渡します。 以下のコードスニペットは、Sessionsをインストールする方法を示しています...

  • ... embeddedServer関数呼び出し内。
  • ... Applicationクラスの拡張関数である、明示的に定義されたmodule内。
kotlin
kotlin

Sessionsプラグインは、特定のルートにもインストールできます。 これは、異なるアプリケーションリソースに対して異なるSessions設定が必要な場合に役立つことがあります。

セッション設定の概要

Sessionsプラグインを設定するには、以下の手順を実行する必要があります。

  1. データクラスの作成: セッションを設定する前に、セッションデータを保存するためのデータクラスを作成する必要があります。

  2. サーバーとクライアント間でデータを渡す方法を選択: Cookieまたはカスタムヘッダーを使用します。CookieはプレーンなHTMLアプリケーションに適しており、カスタムヘッダーはAPI向けです。

  3. セッションペイロードの保存場所を選択: クライアントまたはサーバー。シリアライズされたセッションデータをCookie/ヘッダー値を使用してクライアントに渡すか、ペイロードをサーバーに保存しセッション識別子のみを渡すことができます。

    セッションペイロードをサーバーに保存したい場合は、*保存方法*を選択できます。サーバーのメモリ内、またはフォルダ内です。セッションデータを保持するためのカスタムストレージを実装することもできます。

  4. セッションデータの保護: クライアントに渡される機密性の高いセッションデータを保護するために、セッションのペイロードを署名および暗号化する必要があります。

Sessionsの設定後、ルートハンドラー内でセッションデータを取得および設定できます。

データクラスの作成

セッションを設定する前に、セッションデータを保存するためのデータクラスを作成する必要があります。 たとえば、以下のUserSessionクラスはセッションIDとページビュー数を保存するために使用されます。

kotlin
@Serializable
data class UserSession(val id: String, val count: Int)

複数のセッションを使用する場合は、複数のデータクラスを作成する必要があります。

Cookieを使用してセッションデータを渡すには、install(Sessions)ブロック内で、指定された名前とデータクラスを持つcookie関数を呼び出します。

kotlin
install(Sessions) {
    cookie<UserSession>("user_session")
}

上記の例では、セッションデータはSet-Cookieヘッダーに追加されたuser_session属性を使用してクライアントに渡されます。cookieブロック内で他のCookie属性を渡すことで、それらを構成できます。たとえば、以下のコードスニペットは、Cookieのパスと有効期限を指定する方法を示しています。

kotlin
install(Sessions) {
    cookie<UserSession>("user_session") {
        cookie.path = "/"
        cookie.maxAgeInSeconds = 10
    }
}

必要な属性が明示的に公開されていない場合は、extensionsプロパティを使用します。たとえば、SameSite属性は次のように渡すことができます。

kotlin
install(Sessions) {
    cookie<UserSession>("user_session") {
        cookie.extensions["SameSite"] = "lax"
    }
}

利用可能な設定の詳細については、CookieConfigurationを参照してください。

アプリケーションを本番環境にデプロイする前に、secureプロパティがtrueに設定されていることを確認してください。 これにより、安全な接続を介したCookieの転送のみが有効になり、HTTPSダウングレード攻撃からセッションデータを保護します。

カスタムヘッダーを使用してセッションデータを渡すには、install(Sessions)ブロック内で、指定された名前とデータクラスを持つheader関数を呼び出します。

kotlin
install(Sessions) {
    header<CartSession>("cart_session")
}

上記の例では、セッションデータはcart_sessionカスタムヘッダーを使用してクライアントに渡されます。 クライアント側では、セッションデータを取得するために各リクエストにこのヘッダーを追加する必要があります。

クロスオリジンリクエストを処理するためにCORSプラグインを使用している場合は、以下のようにカスタムヘッダーをCORS設定に追加します。

kotlin
install(CORS) {
    allowHeader("cart_session")
    exposeHeader("cart_session")
}

セッションペイロードの保存: クライアント vs サーバー

Ktorでは、セッションデータを2つの方法で管理できます。

  • クライアントとサーバー間でセッションデータを渡す

    cookieまたはheader関数にセッション名のみを渡す場合、セッションデータはクライアントとサーバー間で渡されます。この場合、クライアントに渡される機密性の高いセッションデータを保護するために、セッションのペイロードを署名および暗号化する必要があります。

  • セッションデータをサーバーに保存し、セッションIDのみをクライアントとサーバー間で渡す

    そのような場合、サーバー上でペイロードをどこに保存するかを選択できます。たとえば、セッションデータをメモリ内、指定されたフォルダ内、または独自のカスタムストレージを実装して保存できます。

サーバーへのセッションペイロードの保存

Ktorでは、セッションデータをサーバーに保存し、セッションIDのみをサーバーとクライアント間で渡すことができます。この場合、サーバー上でペイロードをどこに保持するかを選択できます。

インメモリストレージ

SessionStorageMemoryを使用すると、セッションの内容をメモリに保存できます。このストレージは、サーバーの実行中にデータを保持し、サーバーが停止すると情報を破棄します。たとえば、次のようにCookieをサーバーメモリに保存できます。

kotlin
cookie<CartSession>("cart_session", SessionStorageMemory()) {
}

完全な例はこちらで確認できます: session-cookie-server

SessionStorageMemoryは開発目的のみを意図しています。

ディレクトリストレージ

directorySessionStorageは、指定されたディレクトリ内のファイルにセッションデータを保存するために使用できます。たとえば、build/.sessionsディレクトリ内のファイルにセッションデータを保存するには、次のようにdirectorySessionStorageを作成します。

kotlin
header<CartSession>("cart_session", directorySessionStorage(File("build/.sessions"))) {
}

完全な例はこちらで確認できます: session-header-server

カスタムストレージ

Ktorは、カスタムストレージを実装できるSessionStorageインターフェースを提供します。

kotlin
interface SessionStorage {
    suspend fun invalidate(id: String)
    suspend fun write(id: String, value: String)
    suspend fun read(id: String): String
}

3つの関数はすべてサスペンド関数です。SessionStorageMemoryを参考にすることができます。

セッションデータの保護

セッションデータの署名

セッションデータに署名することで、セッションの内容が改変されるのを防ぎますが、ユーザーはこの内容を見ることができます。 セッションに署名するには、SessionTransportTransformerMessageAuthenticationコンストラクタに署名キーを渡し、このインスタンスをtransform関数に渡します。

kotlin
install(Sessions) {
    val secretSignKey = hex("6819b57a326945c1968f45236589")
    cookie<CartSession>("cart_session", SessionStorageMemory()) {
        cookie.path = "/"
        transform(SessionTransportTransformerMessageAuthentication(secretSignKey))
    }
}

SessionTransportTransformerMessageAuthenticationはデフォルトの認証アルゴリズムとしてHmacSHA256を使用しますが、これは変更可能です。

セッションデータの署名と暗号化

セッションデータを署名および暗号化することで、セッションの内容が読み取られたり、改変されたりするのを防ぎます。 セッションを署名および暗号化するには、SessionTransportTransformerEncryptコンストラクタに署名/暗号化キーを渡し、このインスタンスをtransform関数に渡します。

kotlin
install(Sessions) {
    val secretEncryptKey = hex("00112233445566778899aabbccddeeff")
    val secretSignKey = hex("6819b57a326945c1968f45236589")
    cookie<UserSession>("user_session") {
        cookie.path = "/"
        cookie.maxAgeInSeconds = 10
        transform(SessionTransportTransformerEncrypt(secretEncryptKey, secretSignKey))
    }
}

Ktorバージョン3.0.0暗号化メソッドが更新されたことに注意してください。 以前のバージョンから移行する場合は、既存のセッションとの互換性を確保するために、SessionTransportTransformerEncryptのコンストラクタでbackwardCompatibleReadプロパティを使用してください。

デフォルトでは、SessionTransportTransformerEncryptAESHmacSHA256アルゴリズムを使用しますが、これらは変更可能です。

署名/暗号化キーはコードで指定すべきではありません。 署名/暗号化キーを保存し、環境変数を使用してそれらを初期化するために、設定ファイルでカスタムグループを使用できます。

セッションコンテンツの取得と設定

特定のルートのセッションコンテンツを設定するには、call.sessionsプロパティを使用します。setメソッドを使用すると、新しいセッションインスタンスを作成できます。

kotlin
get("/login") {
    call.sessions.set(UserSession(id = "123abc", count = 0))
    call.respondRedirect("/user")
}

セッションコンテンツを取得するには、登録済みのセッション型のいずれかを型パラメータとして受け取るgetを呼び出すことができます。

kotlin
get("/user") {
    val userSession = call.sessions.get<UserSession>()
    if (userSession != null) {
}

たとえば、カウンターをインクリメントするためにセッションを変更するには、データクラスのcopyメソッドを呼び出す必要があります。

kotlin
get("/user") {
    val userSession = call.sessions.get<UserSession>()
    if (userSession != null) {
        call.sessions.set(userSession.copy(count = userSession.count + 1))
        call.respondText("Session ID is ${userSession.id}. Reload count is ${userSession.count}.")
    } else {
        call.respondText("Session doesn't exist or is expired.")
    }
}

何らかの理由でセッションをクリアする必要がある場合(たとえば、ユーザーがログアウトした場合)、clear関数を呼び出します。

kotlin
get("/logout") {
    call.sessions.clear<UserSession>()
    call.respondRedirect("/user")
}

完全な例はこちらで確認できます: session-cookie-client

遅延セッション取得

デフォルトでは、Ktorはセッションを含むすべてのリクエストに対して、ルートが実際に必要としているかどうかにかかわらず、ストレージからセッションを読み取ろうとします。この動作は、特にカスタムセッションストレージを使用するアプリケーションにおいて、不要なオーバーヘッドを引き起こす可能性があります。

io.ktor.server.sessions.deferredシステムプロパティを有効にすることで、セッションの読み込みを遅延させることができます。

kotlin
System.setProperty("io.ktor.server.sessions.deferred", "true")

以下の実行可能な例は、Sessionsプラグインの使用方法を示しています。