使いやすい認証機構を実現する「Apache Shiro」
今回取り上げる「Apache Shiro 」は、Javaアプリケーション向けに開発された認証と承認のためのオープンソースのフレームワークです。Shiroを使うことで、ログインなどの認証の仕組みや、アクセス管理、セッション管理などといった機構を、容易にアプリケーションに付け加えることができるようになります。
JDKにはJAAS(Java Authentication and Authorization Service)という認証・承認サービスが用意されていますが、JAASで提供されるAPIはあまり使い勝手が良くなく、わかりにくいという意見が大多数を占めていました。ShiroはJAASよりも理解しやすく、簡単に利用できる認証・承認の仕組みを提供する目的で開発されました。Shiroを利用するメリットとしては次のようなものが挙げられています。
理解しやすい簡潔なAPI
認証・承認に必要な一通りの機能を包括的にカバー
さまざまな環境に対応するフレキシビリティ
Webアプリケーションへの組込みとが可能
他のフレームワークやアプリケーションとの統合が容易
依存関係が少ない
設定が容易
Shiroでは、大きく分けて以下の4種類の機能が用意されています。
本人認証(Authentication)
リソースのアクセス権管理(Authorization)
セッション管理(Session Management)
キャッシュ管理(Cache Management)
それぞれ後述するセキュリティマネージャを通して利用できるようになっており、複雑な認証機構はセキュリティマネージャによって隠蔽されている点が大きな特徴です。
Apache Shiroのアーキテクチャ
Apache Shiroは大別すると次の3つのパートから構成されます。
サブジェクト(Subject)
アプリケーションからShiroのセキュリティ機構にアクセスするための"ビュー"となるオブジェクト
セキュリティマネージャ(SecurityManager)
セキュリティのためのさまざまなコンポーネントを提供・管理する
認証レルム(Realm)
さまざまなセキュリティ・データと橋渡しの役目をもつコネクタ
図1 Apache Shiroは3つのパートから成る
出典:http://shiro.apache.org/architecture.html
前述の4つの機能はコンポーネント化されてセキュリティマネージャによって管理されます。認証レルムはセキュリティ・データの種類ごとに用意されます。JDBC用のレルム、LDAP用のレルム、Active Directory用のレルム、といった具合です。それぞれのレルムは共通のインターフェースを持つため、任意に入れ替えて使用できるようになっています。つまり、使用する認証レルムを変えれば、共通の方法で異なるセキュリティデータにアクセスできるということです。
図2 Apache Shiroのアーキテクチャ
出典:http://shiro.apache.org/architecture.html
Apache Shiroでユーザ認証を行う
Shiroはこのページ よりダウンロードできます。全機能を含むバイナリは「shiro-all」で、それ以外に個別のフレームワークやツール向けのバイナリが用意されています。ソースコードをダウンロードした場合、Mavenを使ってビルドできます。
今回はshiro-all(ファイル名shiro-all-1.1.0.jar)を使うものとして解説を進めます。shiro-allを使う場合、Shiro本体以外にSLF4J 、Apache Commons BeanUtils 、Apache 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アプリケーションでの利用方法を解説します。