akka-http-sessionによるセッション管理

Akka HTTPはプリミティブなHTTPツールキットであり、標準ではセッション管理の機能を持っていません。Akka HTTPにセッション管理機能を追加するためのライブラリとしてSoftwareMill社が開発しているakka-http-sessionというものがあります。

github.com

このライブラリを使うとAkka HTTPでセッション管理のためのDSLを利用できるようになります。セッション情報はカスタムHTTPヘッダまたはクッキーでクライアントに送信されます。設定で暗号化することができる他、オプションのモジュールを使用することでJWTを使用することもできます。また、CSRFプロテクション(クッキーの場合のみ)や長期間セッションを維持するためのリフレッシュトークンもサポートされています。

ここでは簡単な例を紹介します。まずはbuild.sbtに以下の依存関係を追加します。

"com.softwaremill.akka-http-session" %% "core" % "0.5.3"

セッションに格納するクラスを作っておきます。

case class Session(userId)

実際のコードは以下のような感じになります。Akka HTTP標準のDSLと同じ感じで記述することができます。特に難しいところはないと思います。SessionConfigの作成時にSessionUtil.randomServerSecret()でランダムなsecretを与えていますが、サーバを複数台立てる場合や再起動してもセッションが継続するようにしたい場合は設定ファイルに切り出して固定のsecretを与えるようにするとよいでしょう。

import com.softwaremill.session.SessionDirectives._
import com.softwaremill.session.SessionOptions._
import com.softwaremill.session.SessionResult._
import com.softwaremill.session._

...

val sessionConfig = SessionConfig.default(SessionUtil.randomServerSecret())
implicit val sessionManager = new SessionManager[Session](sessionConfig)

// ログイン
path ("login") {
  post {
    formFields("userId", "password"){ case (userId, password) =>
      if(userId == "admin" && password == "admin"){
        setSession(oneOff, usingCookies, Session(userId)) {
          complete(StatusCodes.OK)
        }
      } else {
        complete(StatusCodes.Unauthorized)
      }
    }
  }
} ~
// ログアウト
path ("logout") {
  post {
    invalidateSession(oneOff, usingCookies){
      complete(StatusCodes.OK)
    }
  }
} ~
// 要ログインなエンドポイント
path ("required_login"){ case (account) =>
  get {
    requiredSession(oneOff, usingCookies) { session =>
      complete(StatusCodes.OK)
    }
  }
}

設定はデフォルトではapplication.confで行います。デフォルトの設定はこんな感じになっているようです。

セッション情報をHTTPヘッダでやり取りするので巨大なデータの管理には向いていませんが、手軽に使えるのでちょっとした認証をかけたりするのに便利そうです。