TomcatでBasic認証を行う

TomcatBasic認証を使ってみたので、その設定方法をメモ。

Tomcatでちょっとしたことをやりたいときには、Apacheと連携しないとだめかと思っていたのですが、調べてみると思ってたよりもできることが多いことがわかってきました。
たとえば、mod_rewriteを使ったようにURLを静的に見せるのに、Url Rewrite Filterがあったりとか、ライブラリを使わなくても、jspにヘッダやフッタを自動でくっつけたり、国際化に対応したりといろいろできます。

個人的には、TomcatApacheの設定ファイルをいじらなくてもwarファイルを配置するだけで他の環境で動くようにできるのが理想だと思っています(DB関連の設定は必要ですが。)。
Jetty+SQLiteで単独で動くアプリケーションになるならもっとよいですね。

今回、Basic認証Tomcatで実現するに当たって、プロジェクトのMETA-INF/context.xmlで設定することで、conf/tomcat-user.xmlやconf/server.xmlを変更しなくてもよい方法を選択しました。

JDBCレルムの設定

レルムとは

レルムとは、ユーザ名とパスワードの組み合わせのように、 Webアプリケーション(複数のWebアプリケーションのまとまりの場合もあります) のユーザを一意に定めるための"データベース"と、認証された各ユーザに付与されているロールの一覧を列挙するものの両方を合わせたものを指します。

http://www.jajakarta.org/tomcat/tomcat5.0/ja/docs/tomcat-docs/realm-howto.html

デフォルトではUserDatabaseレルムが設定されていますが、今回は元からMySQLを使っており、動的にユーザを増やすこともありそうなので、JDBCレルムを使うことにしました。


データベースに関する設定

Catalinaホーム/common/lib/に事前にJDBCドライバのjarを置いておきます。
まず、MySQLで以下の2つのテーブルを作ります。
tomcat_userテーブル

user varchar(45)
password varchar(45)

ユーザ名とパスワードを保持するテーブルです。

tomcat_roleテーブル

user varchar(45)
role varchar(45)

ユーザ名と所属するロールを保持するテーブルです。

それぞれに以下のデータを入れておきます。

INSERT INTO tomcat_user VALUES("user", "password");
INSERT INTO tomcat_role VALUES("user", "basic");

ユーザ名にuser、パスワードにpasswordを使ってログインを行うことが出来るようになります。


context.xml

プロジェクトにMETA-INF/context.xmlを作成し、以下の記述をします。

<?xml version="1.0" encoding="UTF-8"?>
<Context>
	<Realm className="org.apache.catalina.realm.JDBCRealm" debug="99" resourceName="Basic"
		driverName="org.gjt.mm.mysql.Driver"
		connectionURL="jdbc:mysql:///test_db?useUnicode=true&amp;characterEncoding=UTF-8"
		 connectionName="MySQLのユーザ名" connectionPassword="パスワード"
		 userTable="tomcat_user" userNameCol="user" userCredCol="password"
		 userRoleTable="tomcat_role" roleNameCol="role" />               
</Context>

userTable, userNameCol, userCredCol, userRoleTable, roleNameColで先ほど作ったテーブルと対応させています。


Basic認証の設定

プロジェクトのweb.xmlに以下の追記をします。

<security-constraint>
  <web-resource-collection>
    <web-resource-name>
      Authentication of BasicAuth
    </web-resource-name>
    <url-pattern>/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
    <role-name>basic</role-name>
  </auth-constraint>
</security-constraint>
<login-config>
  <auth-method>BASIC</auth-method>
  <realm-name>Basic</realm-name>
</login-config>
<security-role>
  <role-name>basic</role-name>
</security-role>

どのパターンのURLでアクセスしたときに認証をかけるかやどのロールにアクセスを許可するかを設定します。
で先ほどtomcat_roleに挿入したbasicロールを指定しています。


Tomcat再起動後にプロジェクトのページにアクセスしようとすると、ユーザ名とパスワードの入力が求められ、Basic認証が実行されていることが確認できると思います。

ちなみにこの方法でログインした場合、HttpServletRequestのgetRemoteUserメソッドを使うことでログインしているユーザ名を取得、getUserPrincipalメソッドを使うことでそのユーザの所属するロールを取得できます。


疑問

今回初めてレルムを使った認証を行ったのですが、Tomcatには今回使ったもの以外にもいくつか認証方式が最初から用意されており、Form認証+JDBCレルムを利用すればログイン制御としては十分です。
そこで気になったのは、JavaでWebアプリケーションを作るときには、一般的にこの認証の仕組みを使うことが多いのかということです。
細かい制御が必要なときはSessionを使ったほうがよさそうですので場合によりけりなのでしょうか。