連載
» 2004年11月17日 10時00分 UPDATE

JavaTips 〜アプリケーションサーバ/コンテナ活用編:Tomcatでダイジェスト認証を使う

[佐藤匡剛,@IT]

 Tomcatには、基本認証やダイジェスト認証などの、HTTPによるアクセス認証の機能が組み込まれています。Webアプリケーションに本格的な認証を付けたい場合には、Tomcatのフォーム認証や自前で用意した認証機構などを使う必要がありますが、簡易的にアクセス制限を施したい場合などは、これらのHTTPによる認証で事足りるでしょう。

 そのうち基本認証は、簡単なのでよく利用されます。基本認証では、ユーザーが入力したパスワードは、BASE64という方法で符号化されてネットワーク上を流れます。このBASE64符号化は、そもそも暗号化のための方法ではなく、符号化のアルゴリズムを知っているものならば、誰でも簡単に解読できてしまうものです。そのため、認証時の通信を傍受されると、パスワードが簡単に取得されてしまい、基本的に安全ではありません。

 通信経路の秘密性を保つには、SSL(Server Socket Layer)の導入などが考えられます。この場合、基本認証でも安全な認証ができます。しかし、SSLの導入が難しいこともあるでしょう。そのようなときは、ダイジェスト認証が有効です。ダイジェスト認証では、認証時の通信が暗号化されるので、基本認証に比べて安全に認証を行うことができるのです。

注:ダイジェスト認証では、認証のための情報が暗号化されるだけで、それ以外の送受信データについては一切暗号化されません。従って、クレジットカード番号などの大切な個人情報をHTTP上でやり取りする場合には、やはりSSLを使って、送受信データ全体を暗号化する必要があります。

 なお、Tomcatで基本認証やフォーム認証を利用する方法については、「アクセス制限をweb.xmlの記述だけで実現する」「フォーム認証でログイン画面をカスタマイズする」に、それぞれ説明があります。

ダイジェスト認証とは

 ダイジェスト認証とは、パスワードから生成されるダイジェストのみを使って認証を行う方法です。ダイジェストとは、一方向ハッシュ関数にデータを入力することで得られる値のことです。一方向ハッシュ関数には、入力データからダイジェストを生成することは容易だが、ダイジェストからその入力データを逆方向に復元しようとするのは非常に難しい、という特徴があります。そのため、ネットワーク上をダイジェストのみが流れている限り、そこからパスワードを解読される心配はないというわけです。

 ダイジェスト認証のステップを、簡単に説明しましょう。なお、ここでの説明は、ダイジェスト認証の大まかなイメージを理解していただくためのもので、詳細は省略されています。RFCに定義された実際の認証は、もう少し複雑であることをお断りしておきます。

 まず、クライアントから認証情報を含まないHTTPリクエストが送られてくると、サーバはクライアントへ認証要求を返します。ここで、サーバから送られるレスポンス・ヘッダには、「nonce」および「opaque」という、BASE64符号化または16進数(0〜f)のデータ文字列が含まれています。nonceとは、何らかの方法で認証要求ごとに生成される、一時的なデータを表します。opaqueとは、ランダムに生成されるデータです。これらのデータは、クライアントとサーバとの間で認証が確立されている限り保持されます。

サーバからの認証要求(WWW-Authenticate) サーバからの認証要求(WWW-Authenticate)

 クライアントは、サーバからの認証要求を受け取ると、ユーザー名とパスワードの入力を促すプロンプトを表示します。ユーザー名とパスワードが入力されると、クライアントはサーバへ認証情報を送信します。ここで、クライアントが送信するリクエスト・ヘッダには、ユーザー名とサーバから送られてきたnonce、opaqueデータのほかに、「cnonce」「response」というデータが含まれます。cnonceとは、クライアント側で生成される一時データです。これは、クライアントがリクエストを送信するごとに新たに生成されます。responseが、パスワードの代わりに送信されるデータになります。responseは、ユーザー名とパスワードから作られる文字列をキーとして、nonce、cnonce、opaqueおよびリクエスト先のURIを基に作られる文字列から得られるダイジェストになります。

クライアントからの認証情報送信(Authorization) クライアントからの認証情報送信(Authorization)

 サーバは、正しいパスワードを元に、同じアルゴリズムを用いてresponseの値を生成します。その値が、クライアントから送信されたresponseと一致すれば、クライアントが正しいパスワードを入力したことが分かる、という仕組みです。

注:Tomcatでは、パスワードをダイジェスト化して保存することもできます。こちらは、保存されたパスワードの秘密性を保つためのものです。ダイジェスト認証とは、まったく別のセキュリティ上の手法であることに注意してください。Tomcatでパスワードをダイジェスト化する方法については、「Tomcatのパスワードをダイジェスト化する」を参照してください。

Tomcatでの設定方法

 Tomcatで認証を利用する方法は、基本認証もダイジェスト認証もほぼ同じになります。基本認証を利用するための設定をしたうえで、ダイジェスト認証を利用したいときだけ、Webアプリケーションごとのweb.xmlに対して、下の赤字部分を「BASIC」→「DIGEST」へ変更すればよいのです(基本認証を設定するまでの流れについては、「アクセス制限をweb.xmlの記述だけで実現する」を参照してください)。

Webアプリケーションごとのweb.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" 
  version="2.4">
  ……中略……
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>JavaTIPS samples</web-resource-name>
      <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>javatips</role-name>
    </auth-constraint>
  </security-constraint>
  
  <login-config>
    <auth-method>DIGEST</auth-method>
    <realm-name>JavaTIPS</realm-name>
  </login-config>
  
  <security-role>
    <role-name>javatips</role-name>
  </security-role>
  ……中略……
</web-app>


 これで設定は完了です。……といいたいところですが、残念ながら現在のところ、そういうわけにはいきません。

 Tomcat5.0.xでは、「%CATALINA_HOME%\conf\server.xml」にて、レルム(Realm:認証情報が格納されるデータベースを指す)がデフォルトで“UserDatabase”に設定されています。これは、tomcat-user.xmlを認証情報に用いるレルムの実装の最新版なのですが、執筆時点(Tomcat5.0.27)では、こちらにレルムが設定されているとダイジェスト認証が機能しません。そのため、古い実装として残されている“MemoryRealm”の方へ、レルムを変更してやる必要があります。以下のように、server.xmlを修正します。

注:「%CATALINA_HOME%」は、Tomcatのルートフォルダを示すこととします。Windowsでのデフォルトは、「C:\Program Files\Apache Software Foundation\Tomcat 5.0」です。

server.xml(抜粋)
      ……中略……
   <!-- This Realm uses the UserDatabase configured in the global JNDI
      resources under the key "UserDatabase". Any edits
      that are performed against this UserDatabase are immediately
      available for use by the Realm. -->
   ↓以下をコメントアウトする
   <!--
   <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
         debug="0" resourceName="UserDatabase"/>
   -->

   <!-- Comment out the old realm but leave here for now in case we
      need to go back quickly -->
   ↓以下のコメントアウトを外す
   <Realm className="org.apache.catalina.realm.MemoryRealm"/>
   
   ……中略……


 現状では、UserDatabaseレルムに限らず、MemoryRealm以外のレルムではダイジェスト認証が機能しないようです。セキュリティ上の理由から、レルムの実装に制限があるのが原因のようです。

 今度こそ設定は完了です。Tomcatを再起動後、設定が有効になります。

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

Focus

- PR -

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。