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

第20回 Javaアプリケーション向けの認証フレームワーク「Apache Shiro」

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

Apache Shiroでユーザ認証を行う

Shiroはこのページよりダウンロードできます。全機能を含むバイナリは「shiro-all」で,それ以外に個別のフレームワークやツール向けのバイナリが用意されています。ソースコードをダウンロードした場合,Mavenを使ってビルドできます。

今回はshiro-all(ファイル名shiro-all-1.1.0.jar)を使うものとして解説を進めます。shiro-allを使う場合,Shiro本体以外にSLF4JApache Commons BeanUtilsApache Commons Loggingの各ライブラリを別途ダウンロードしてクラスパスに追加する必要があります。

Shiroを使った認証の起点となるのはSecurityUtilsクラスです。このクラスのstaticメソッドによって,セキュリティマネージャの設定とサブジェクトの取得が行えます。セキュリティマネージャはorg.apache.shiro.mgt.SecurityManagerインターフェース(java.langパッケージに同名のクラスがあるので,必ずフルパスで記述する必要があります)をimplementsしたクラスとして実装されています。たとえばAuthenticatingSecurityManagerやSessionsSecurityManagerなどです。

今回は,.iniファイルからセキュリティマネージャの設定を読み込む方法を使ってみます。.iniファイルからSecurityManagerオブジェクトを作成するには,IniSecurityManagerFactoryクラスを利用して次のように行います。

Factory<org.apache.shiro.mgt.SecurityManager> factory = 
                                             new IniSecurityManagerFactory("shiro.ini");
org.apache.shiro.mgt.SecurityManager manager = factory.getInstance();

SecurityManagerが作成できたら,それをSecurityUtilsにsetSecurityManager()メソッドを使って設定します。

SecurityUtils.setSecurityManager(manager);

サブジェクトはSubjectクラスとして実装されています。これを取得するには,SecurityUtilsのgetSubject()メソッドを呼び出します。

Subject user = SecurityUtils.getSubject();

ユーザ認証はSubjectを介して行うことができるのですが,そのためには認証に使うためのトークンを作成しなければなりません。ユーザ名とパスワードによる認証のためのトークンであればUsernamePasswordTokenクラスで作成します。次のように,第1引数にユーザ名,第2引数にパスワードを引数にしてコンストラクタを呼び出します。

UsernamePasswordToken token = 
		      new UsernamePasswordToken("gihyo", "gihyopass");

このTokenオブジェクトをSubjectのlogin()メソッドに渡して実行することでログイン認証が行われます。次のプログラムは,ログイン認証のための一連の流れを示したものです。

public class FirstShiroSample {
  public static void main(String[] args) {
    // セキュリティマネージャの設定
    Factory<org.apache.shiro.mgt.SecurityManager> factory = 
	            new IniSecurityManagerFactory("classpath:shiro.ini");
    org.apache.shiro.mgt.SecurityManager manager = factory.getInstance();
    SecurityUtils.setSecurityManager(manager);
    
    // Subjectの取得
    Subject user = SecurityUtils.getSubject();
    
    if (!user.isAuthenticated()) {
      try {
        // Tokenの作成
        UsernamePasswordToken token = new UsernamePasswordToken("gihyo", "gihyopass");
        
        // ログイン
        user.login(token);
        
        System.out.println("Login successful.");
      } catch (AuthenticationException ex) {
        System.out.println("Authentication failed.\n" + ex);
      }
    } else {
      System.out.println("This user is authenticated.");
    }
  }
}

login()メソッドは認証に失敗するとAuthenticationException(またはそのサブクラスのException)をスローします。また,すでに認証が完了しているSubjectに関しては,isAuthenticated()メソッドがtrueを返すようになっています。

.iniファイルの記述方法ですが,ユーザ名とパスワードの設定であれば,次に示すように[user]セクションにユーザ名とパスワードを「=」でつなげて記述します。この例の場合はユーザ名が「gihyo⁠⁠,パスワードが「gihyopass」です。今回はとりあえずこの設定だけでOKです。その他に.iniファイルの設定項目に関してはリファレンスマニュアルを参照してください。

[users]
gihyo = gihyopass

.iniファイルが用意できたら,FirstShiroSampleを実行してみましょう。⁠Login successful.』という表示が出れば認証成功です。認証に失敗した場合には,次のようにIncorrectCredentialsExceptionがスローされます。

Authentication failed.
org.apache.shiro.authc.IncorrectCredentialsException: 
    The credentials provided for account 
    [org.apache.shiro.authc.UsernamePasswordToken - gihyo, rememberMe=false]
     did not match the expected credentials.

もし『[main] INFO org.apache.shiro.session.mgt.AbstractValidatingSessionManager - Enabling session validation scheduler...』ようなメッセージが表示される場合には,.iniファイルの[main]セクションに以下の設定を追加することでメッセージは表示されなくなります。

[main]
securityManager.sessionManager.sessionValidationSchedulerEnabled = false

次回は,セッションの使用やWebアプリケーションでの利用方法を解説します。

著者プロフィール

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

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

著書