本格派エンジニアの工具箱

第21回 Apache Shiroを利用して,スタンドアロンプログラムでセッションを有効にする

この記事を読むのに必要な時間:およそ 2 分

Apache Shiroのセッション管理機能

前回に引き続き,Javaアプリケーション向けの認証フレームワークApache Shiroの使い方を紹介します。Shiroには,認証機能に関連していくつかのうれしい付加機能が備わっています。その1つがセッション管理機能です。セッションを使えば,ユーザに紐付いた情報などを一定期間アプリケーション側に保持しておくことができるようになります。

Webアプリケーションであればjavax.servlet.http.HttpSessionなどによってセッションを扱うことができますが,Shiroでは,スタンドアロンのアプリケーションにおいても認証機構と連動したセッションを使うことができるようになっています。

Shiroでセッションを扱うにはorg.apache.shiro.session.Sessionインターフェース(とその実装クラス)を利用します。使い方はHttpSessionとよく似ています。まず,Sessionオブジェクトは次ようにSubjectのgetSession()メソッドを用いて取得します。

// セッションの取得(作成)
Subject user = SecurityUtils.getSubject();
Session session = user.getSession(true);

このメソッドは,すでにセッションが確立している場合にはそのSessionoオブジェクトを返します。まだセッションがない場合には,引数がfalseのときはnullを,trueのときは新たにSessionオブジェクトを生成して返します。

セッションへのキーと値の設定はaddAttribute()メソッドを使います。このメソッドにはキーとなるオブジェクトと,それに関連付ける値のオブジェクトをセットで渡します。値を取り出すには,getAttribute()メソッドにキーを渡せば,そのキーに関連付けられた値のオブジェクトが返されます。

// セッションにキーと値をセット
session.setAttribute("key", "value");

// セッションから値の取得
String attribute = session.getAttribute("key");

次のコードは,Shiroによる認証とセッション管理を利用したプログラムの例です。ログイン後にコンソールから入力されたテキストをセッションに記録します。SubjectクラスのisAuthenticated()メソッドは,そのSubjectが認証済みである場合にtrueを返すというものです。つまりこのプログラムは,初回はログイン処理を行ってセッションを作成し,以後はセッションからの値の読み出しと新しい値の設定を繰り返し行うようになっているわけです。そして"LOGOUT"が入力された場合に,ログアウト処理を行ってプログラムを終了します。

public class SessionSample {
  public static void main(String[] args) {
    // セキュリティマネージャの設定
    Factory factory = 
            new IniSecurityManagerFactory("classpath:resources/manager.ini");
    SecurityUtils.setSecurityManager(factory.getInstance());
    
    // Subjectの取得
    Subject user = SecurityUtils.getSubject();

    while(true) {
      Session session = null;
      if (!user.isAuthenticated()) {
        try {
          // Tokenの作成
          UsernamePasswordToken token = 
                  new UsernamePasswordToken("gihyo", "gihyopass");
        
          // ログイン
          user.login(token);
          System.out.println("----ログインしました。");
        
          // セッションの取得(作成)
          session = user.getSession(true);
          
          // コンソールからの入力値をセッションのプロパティにセット
          System.out.println("----任意のテキストを入力してください。");
          String input = System.console().readLine();
          session.setAttribute("input", input);
        } catch (AuthenticationException ex) {
          System.out.println("Authentication failed.\n" + ex);
        }
      } else {
        System.out.println("----ログイン中です。");
      
        if ((session = user.getSession(false)) != null) {
          System.out.println("前回の入力テキスト: " + session.getAttribute("input"));
          // コンソールからの入力をセッショプロパティにセット
          // ただし"LOGOUT"だった場合はログアウト処理
          System.out.println("----任意のテキストを入力してください。");
          String input = System.console().readLine();
          if (input.equals("LOGOUT")) {
            user.logout();
            System.out.println("----ログアウトしました。");
            break;
          } else {
            session.setAttribute("input", input);
          }
        }
      }
    }
  }
}

このプログラムの実行例は以下のようになります。Sessionオブジェクトを経由して情報が記録できていることが確認できます。

----ログインしました。
----任意のテキストを入力してください。
Hello!                 <--テキストを入力
----ログイン中です。
前回の入力テキスト: Hello!
----任意のテキストを入力してください。
World!                 <--テキストを入力
----ログイン中です。
前回の入力テキスト: World!
----任意のテキストを入力してください。
LOGOUT                 <--テキストを入力
----ログアウトしました。

Shiroにおけるセッションは,セッションストレージと呼ばれるDAO(Data Access Object)形式のデータ永続化の仕組みを利用して情報を記憶しています。デフォルトではメモリ上に永続化するシンプルな実装が使われますが,その他にキャッシュ機構を利用して永続化する仕組みのセッションストレージを利用することができます。そして,商用レベルのアプリケーションではそのような実装を使うことが推奨されます。

とくにEHCacheを利用した実装についてはshiro-ehcacheパッケージ(shiro-allパッケージにも含まれます)として公式にサポートされているので,比較的簡単に利用することができます。詳細は公式のリファレンスを参照してください。

著者プロフィール

杉山貴章(すぎやまたかあき)

ONGS Inc.所属のプログラマ兼テクニカルライター。雑誌,書籍,Webメディアで多数の著作をもつ。

著書

コメント

コメントの記入