Copy & Paste Engineer

【Elixir】Phoenixでカスタムセッションストアを作る

【Elixir】Phoenixでカスタムセッションストアを作る

Elixir Phoenixで自作のセッションストアを作る方法についてやっていきます。 今回はセッション情報を各セッションID名のJSONに保存するというセッションストアを作っていきます。

環境

必要な依存関係の解決

最初に、このチュートリアルで必要な依存関係を追加しましょう。 この例では、JSONのエンコードおよびデコードを行うためのライブラリとしてjasonを使用します。 以下のようにmix.exsファイルに依存関係を追加します。

Jason

defp deps do
  [
    {:jason, "~> 1.3"}
  ]
end

その後、以下のコマンドを実行して依存関係を取得します。

$ mix deps.get

なぜ、セッションストアを自作するのか

通常、PhoenixではCookieやETSなど既存のセッションストアを使用しますが、場合によっては独自のストレージメカニズムを必要とすることもあります。 今回はそのようなケースに対応するため、Plug.Session.Store の実装を使用してカスタムセッションストアを作ります。 なお、今回はサンプルのためセッションデータはローカルのJSONファイルとして保存します。

Plug.Session.Storeとは

Plug.Session.StorePlug.Session が使用するストレージのインターフェイスです。以下の3つの関数を実装する必要があります。

自作のセッションストアを作成する

では、実際にMySessionStoreというモジュールを作成します。 これはPlug.Session.Storebehaviourを実装します。 ここでは、セッションデータが保存されるディレクトリのパスを定数として定義します。

defmodule MySessionStore do
  @moduledoc """
  自作のセッションストアモジュール


  """

  @session_dir "./"

  @behaviour Plug.Session.Store

  @impl true
  def init(_opts) do
    # オプションの初期化をここで行うことができます
  end

  @doc """
  セッションID(sid)を使ってセッションデータを取得します。
  sidはセッションを一意に識別するためのIDです。
  """
  @impl true
  def get(_conn, sid, _opts) do
    case File.read("#{@session_dir}/#{sid}.json") do
      {:ok, json} ->
        {sid, Jason.decode!(json)}

      {:error, _reason} ->
        {sid, %{}}
    end
  end

  @doc """
  新しいセッションを生成し、そのデータを保存します。
  新規セッションのID(sid)はランダムなバイト列をエンコードしたものです。
  """
  @impl true
  def put(_conn, nil, new_data, _opts) do
    sid = :crypto.strong_rand_bytes(16) |> Base.url_encode64()
    put(nil, sid, new_data, nil)

    sid
  end

  @doc """
  既存のセッションを更新し、そのデータを保存します。
  sidを元にJSONファイルを探し、新たなデータでそのファイルを更新します。
  """
  @impl true
  def put(_conn, sid, new_data, _opts) do
    File.write!("#{@session_dir}/#{sid}.json", Jason.encode!(new_data))

    sid
  end

  @doc """
  既存のセッションを削除します。
  sidに対応するJSONファイルを削除します。
  """
  @impl true
  def delete(_conn, sid, _opts) do
    File.rm!("#{@session_dir}/#{sid}.json")
    :ok
  end
end

自作のセッションストアを有効にする

これまで作成した自作のセッションストアを有効にするためには、Phoenixのエンドポイント設定を更新する必要があります。 具体的には、lib/your_app_web/endpoint.ex ファイル内の plug Plug.Session の行を次のように書き換えます。

plug Plug.Session,
  store: MySessionStore,
  key: "_your_app_key",
  signing_salt: "your_signing_salt"

ここで、store: には自作のセッションストアモジュール名を指定します。 また、key:signing_salt: はセッションデータの署名に使用されるため、それぞれ適切な値を設定してください。

まとめ

以上で、Phoenixで自作のセッションストアを作る方法について説明しました。この例では、シンプルなJSONファイルにデータを 保存していますが、要件に応じてMySQLやPostgreSQLなどのデータベースに保存することも可能です。

ただし、実際の運用においては、セッションデータを平文でファイルに保存することは、パフォーマンスとセキュリティの観点から適切ではないかもしれません。 この記事は主に教育的な目的のためのもので、実際のプロジェクトでは適切なセキュリティ対策を講じることが重要です。