Webアプリケーションへのインテグレーション
前々回に引き続いて、Javaアプリケーション向けの認証フレームワーク「Apache Shiro」(以下Shiro)の使い方を解説します。ShiroはServletによるWebアプリケーションに組み込んで利用することもできます。Shiroを利用することでWebサイトへのログイン管理が簡単になる他、ページごとに認証方法を変えるなどといった細かな設定も容易に行えるようになります。
ShiroとWebアプリとの連携はServletフィルタの機構を利用して行います。Shiroにはjavax.servlet.Filterインターフェースを実装した基底クラスorg.apache.shiro.web.servlet.AbstractFilterと、これを継承したさまざまなクラスが用意されています。Webアプリ側では、クライアントからのリクエストがこれらのフィルタを経由するようweb.xmlに設定を追加するだけで、Shiroによる認証機構を利用できるようになります。
web.xmlの設定は次のように記述します(ただし、次期バージョンのShiro 1.2からは記述方法が少し変わります。詳細はリファレンスマニュアルを参照してください)。IniShiroFilterはShiroの設定をINIファイルから読み込むフィルタです。この例では、設定ファイルshiro.iniを/WEB-INF/ディレクトリに配置し、それを読み込むようになっています。
その他に、Shiroの設定を直接web.xmlに記述してしまう方法もあります。その場合はinit-paramのparam-nameを「config」として、設定内容をparam-valueの値として直接書き込みます。
INIファイルの書き方は、基本的にはスタンドアロンの場合と同様です。ただし、Webアプリで利用する場合にはここにページごとに使用する認証フィルタの設定を記述しておく必要があります。ページごとの認証フィルタの設定は[urls]セクションに記述します。形式は「【コンテキストルートパス】=【フィルタの種類】」です。パスにはワイルドカードとして「**」を使うこともできます。たとえば「/user/**」と記述した場合には、/user/ディレクトリ以下のすべてのコンテンツへのアクセスが対象となります。
認証フィルタには下表のようなものがあります。その他に、Shiro 1.2からはログアウト処理を行う「logout」やセッションを作成しない「noSessionCreation」などが利用できるようになる予定です。複数の認証フィルタを適用することも可能で、その場合にはINIファイルの設定でフィルタ名をコンマで区切って記述します。
表 認証フィルタの種類
フィルタ名 | 内容 | 使用されるクラス名(パッケージ名は省略) |
anon | 認証を行わない。 | AnonymousFilter |
authc | フォームを使ったログイン認証を行う。認証されていないアクセスはログインページへリダイレクトする | FormAuthenticationFilter |
authcBasic | HTTPのBasic認証を行う。 | BasicHttpAuthenticationFilter |
perms | ログイン中のユーザからのコンテンツごとのアクセス権を制御する | PermissionsAuthorizationFilter |
port | 特定のポートへのリクエストのみ許可する。 | PortFilter |
rest | HTTPリクエスト別にアクセス制御を行う。RESTサービスなどの実装に利用する | HttpMethodPermissionFilter |
roles | ロール別のアクセス権を制御する | RolesAuthorizationFilter |
ssl | SSLによる認証を行う | SslFilter |
user | 既知のユーザ(認証済みか、またはRememberMe機構によって記憶されたユーザ)からのアクセスのみ許可する | UserFilter |
認証フィルタもServletフィルタの一種です。たとえば「authc」を指定されているページへのアクセスではFormAuthenticationFilterが使われます。つまりクライアントからのアクセスは最初にweb.xmlに設定されたフィルタを通じてアクセスするページごとの認証フィルタに振り分けられることで、Shiroの認証機構の管理下に置かれるというわけです。
以下に、設定ファイルshiro.iniの記述例を示します。この例では、コンテキストルートのindex.jspとlogin.jspは「anon」が指定しされているので認証なしでアクセスできますが、userディレクトリ以下のコンテンツにアクセスした場合には、「authc」フィルタによる認証が必要となります。authcは認証済みのユーザ以外からのアクセスのみ受け付け、それ以外はログインページにリダイレクトします。ログインページは[filters]セクションのauthc.loginUrlプロパティに設定します。[users]セクションにはこれまで同様、ユーザ名とパスワードを記述してあります。
ログイン処理を行うプログラムの作成
続いてログインページやServletのプログラムを作っていきましょう。まず、ログインページとなる/login.jspでは、次のようにユーザ名とパスワードを入力できるようにします。
ログインページからの入力を処理するServletはLogin.javaとして次のように作りました。
ここでは、受け取ったユーザ名とパスワードからTokenを作成し、それを使ってログイン処理を行っています。ログインに成功したら/user/content.jspにリダイレクトします。/user/conten.jspは次のようにしました。単にテキストとログアウトページへのリンクを表示するだけのファイルです。ポイントは、このファイルをauthcフィルタが適用される/user/ディレクトリ以下に配置することです。
ログアウトを行うプログラムはLogout.javaとして、Subjectを取得してlogout()メソッドを呼び出す処理を実行します。次のような感じです。
web.xmlへの記述内容は次のようになります。shiro.iniは上で掲載したものと同じで、これを/WEB-INF/ディレクトリに配置しましょう。
以上で完成です。Webサーバにデプロイしてブラウザから/user/content,jspにアクセスしてみましょう。/user/以下はauthcフィルタによって保護されたエリアなので、ログインしていない状態ではl/login.jspにリダイレクトされるはずです。/login.jspでは図1のように表示されるので、ここでユーザ名とパスワードを入力してログインしてください。
ログインに成功すると、図2のように/user/content.jspにアクセスできるようになります。
カスタムタグライブラリを使う
ShiroにはWebアプリケーションで使うためのJSP/GSP向けのカスタムタグライブラリが用意されています。これを利用することで、認証済みか否かで表示内容を変えるなどといった処理が簡単に記述できるようになります。
たとえば、userタグで囲まれた内容は、認証済みの場合にのみ表示されるようになります。逆に、未認証の場合にのみ表示したい内容がある場合にはgestタグを使うと便利です。次の例は、この2つのタグを使って認証済みか否かで表示内容を変えるものです。
認証が行われていないユーザに対しては、図3のように表示されます。一方、認証済みであれば図4のような表示になります。principalタグは、Subjectオブジェクトのユーザ名を取得するカスタムタグです。
Webアプリケーションにユーザ認証は不可欠ですが、Apache Shiroを使えばこのように簡単にその仕組みを組み込むことができる上、コンテンツごとのアクセス権管理も容易に行えます。今回はユーザ情報の設定にINIファイルのみ使いましたが、各種レルムを導入すれば、LDAPやデータベースをはじめとしたさまざまな認証機構と組み合わせることもできるので、実用性は極めて高いと言えるでしょう。