Apache Shiroのセッション管理機能
前回に引き続き、Javaアプリケーション向けの認証フレームワーク「Apache Shiro」の使い方を紹介します。Shiroには、認証機能に関連していくつかのうれしい付加機能が備わっています。その1つがセッション管理機能です。セッションを使えば、ユーザに紐付いた情報などを一定期間アプリケーション側に保持しておくことができるようになります。
Webアプリケーションであればjavax.servlet.http.HttpSessionなどによってセッションを扱うことができますが、Shiroでは、スタンドアロンのアプリケーションにおいても認証機構と連動したセッションを使うことができるようになっています。
Shiroでセッションを扱うにはorg.apache.shiro.session.Sessionインターフェース(とその実装クラス)を利用します。使い方はHttpSessionとよく似ています。まず、Sessionオブジェクトは次ようにSubjectのgetSession()メソッドを用いて取得します。
このメソッドは、すでにセッションが確立している場合にはそのSessionoオブジェクトを返します。まだセッションがない場合には、引数がfalseのときはnullを、trueのときは新たにSessionオブジェクトを生成して返します。
セッションへのキーと値の設定はaddAttribute()メソッドを使います。このメソッドにはキーとなるオブジェクトと、それに関連付ける値のオブジェクトをセットで渡します。値を取り出すには、getAttribute()メソッドにキーを渡せば、そのキーに関連付けられた値のオブジェクトが返されます。
次のコードは、Shiroによる認証とセッション管理を利用したプログラムの例です。ログイン後にコンソールから入力されたテキストをセッションに記録します。SubjectクラスのisAuthenticated()メソッドは、そのSubjectが認証済みである場合にtrueを返すというものです。つまりこのプログラムは、初回はログイン処理を行ってセッションを作成し、以後はセッションからの値の読み出しと新しい値の設定を繰り返し行うようになっているわけです。そして"LOGOUT"が入力された場合に、ログアウト処理を行ってプログラムを終了します。
このプログラムの実行例は以下のようになります。Sessionオブジェクトを経由して情報が記録できていることが確認できます。
Shiroにおけるセッションは、セッションストレージと呼ばれるDAO(Data Access Object)形式のデータ永続化の仕組みを利用して情報を記憶しています。デフォルトではメモリ上に永続化するシンプルな実装が使われますが、その他にキャッシュ機構を利用して永続化する仕組みのセッションストレージを利用することができます。そして、商用レベルのアプリケーションではそのような実装を使うことが推奨されます。
とくにEHCacheを利用した実装についてはshiro-ehcacheパッケージ(shiro-allパッケージにも含まれます)として公式にサポートされているので、比較的簡単に利用することができます。詳細は公式のリファレンスを参照してください。
セッションの開始/終了時にリスナを起動する
Shiroのセッションでは、開始時と終了時のイベントを受け取るリスナを登録することもできます。リスナはorg.apache.shiro.session.SessionListenerインターフェースをimplementsして作ります。以下に例を示します。
SessionListenerAdapterクラスはSessionListenerの空の実装です。onStart()はセッションが開始されたときに呼び出されるメソッドです。onStop()はセッションが停止されたとき、具体的にはSessionクラスのstop()メソッドが呼ばれたときに呼び出されます。stop()メソッドはSubjectのlogout()メソッドの実行時にも自動的に呼ばれるので、ログアウトした際にもこリスナが反応するということです。
リスナの登録は、iniファイルに設定を記述することで行います。上の例ではmanager.iniにからSecurityManagerの設定を読み込んでいるので、このmanager.iniの[main]セクションにおいて、securityManager.sessionManager.sessionListenersプロパティに次の例のように登録したいリスナのクラス名を設定します。なお、リスナは複数登録することもできます。
この状態でSessionSampleを実行すると、以下のように、セッションの開始時と終了時にそれぞれリスナのメソッドが実行されることが確認できます。
なお、使用するSessionManagerの実装によっては、設定ファイルではなくプログラム内でSessionListenerを登録することもできます。デフォルトで使用されるSessionManager実装のDefaultSessionManagerクラスもそのひとつです。このクラスに用意されているsetSessionListeners()メソッドを使い、次のようにSessionListenerを格納したCollectionオブジェクトを渡すことで登録を行います。