ベーシック認証や IP アドレスによる認証を行うコードは、ほとんど書き直すことがない。いざコードを書こうとしたら忘れてしまっていたということがないように、Apache 2.2.x と Tomcat 6.0.x/Tomcat 7.0.x を連携し、Apche が取得する情報を Tomcat で取得する方法をメモとして残しておくことにした。
Apache と Tomcat の連携方法
HTTP プロキシーである mod_proxy_http を使う方法と、AJP で接続する mod_proxy_ajp を使う方法がある。結論から述べると、
- Apache と Tomcat は AJP で連携する
- Tomcat の Connector の設定で tomcatAuthentication を false に設定する(<Connector port=”8009″ protocol=”AJP/1.3″ redirectPort=”8443″ tomcatAuthentication=”false”/>)
の2つが必要だ。それぞれ検証してみた結果は、以下の通りだ。
mod_proxy_http を使用した場合
Apache の設定は、以下の通りだ。
ProxyPass /app http://192.168.1.2:8080/app
Tomcat で動作する Java のコードは以下の通り。
HttpServletRequest request; // どこかから渡された request System.err.println(request.getRemoteHost()); // 192.168.1.1 <= Apache の IP アドレス System.err.println(request.getRemoteUser()); // null
mod_proxy_http を利用した場合、HTTP プロキシー接続になるためクライアントの IP アドレスは Apache の IP アドレスになり、ベーシック認証のユーザーも取得できない。
mod_proxy_ajp を使用した場合(1)
Tomcat をデフォルトの設定で、Apache を以下のように設定した。
ProxyPass /app ajp://192.168.1.2:8009/app
Tomcat で動作する Java のコードは以下の通り。
HttpServletRequest request; // どこかから渡された request System.err.println(request.getRemoteHost()); // 192.168.1.100 <= クライアントの IP アドレス System.err.println(request.getRemoteUser()); // null
AJP で接続した場合、クライアントの IP アドレスは正しく取得できる。ベーシック認証のユーザーは、Tomcat 側の設定がデフォルトのままでは取得できず null になる。
mod_proxy_ajp を使用した場合(2)
Tomcat の設定ファイル server.xml の Connector のアトリビュートに、「tomcatAuthentication」がある。Tomcat 6のドキュメントを読むと、以下のような記述がある。
If set to true, the authentication will be done in Tomcat. Otherwise, the authenticated principal will be propagated from the native webserver and used for authorization in Tomcat. The default value is true.
認証を Tomcat で行う場合は true に、Web Server から引き継いで利用する場合は false に設定すればよいのだが、デフォルトが true なので自分で指定する必要がある。server.xml の AJP のコネクターに、tomcatAuthentication のアトリビュートを加える。
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" tomcatAuthentication="false"/>
Apache の設定は、(1)の場合と同じだ。
ProxyPass /app ajp://192.168.1.2:8009/app
Tomcat で動作する Java のコードは以下の通り。
HttpServletRequest request; // どこかから渡された request System.err.println(request.getRemoteHost()); // 192.168.1.100 <= クライアントの IP アドレス System.err.println(request.getRemoteUser()); // user
AJP で接続して tomcatAuthentication を false にすれば、クライアントの IP アドレスもベーシック認証のユーザーも Tomcat 側のコードで取得できた。