「Java/Tomcat/Basic認証(UserDatabaseRealm)+DIGEST認証」の編集履歴(バックアップ)一覧に戻る

Java/Tomcat/Basic認証(UserDatabaseRealm)+DIGEST認証 - (2015/01/27 (火) 13:38:21) のソース

TomcatのBasic認証を使って、「管理画面、会員用コンテンツ、公開コンテンツ」の三段階のアクセス管理を設定してみましょう。
※ちょっと設定を変えると&link_anchor(digest){DIGEST認証}にもなるよ。

* ■目次
#contents(fromhere=true)

* ポイント
- Basic認証を利用するには、まず「&link_anchor(web.xml){web.xml}」で認証方式とアクセス制御を設定するURLと権限の設定をします。
- その上で、認証するユーザー、ロール(役割、権限)の設定をTomcatに指定するために以下の設定が必要になります。
-- 「&link_anchor(server.xml){server.xml}」でレルム(認証情報の取り扱い方法)の設定
--- 今回利用する「UserDatabeseRealm」はTomcatインストール時のデフォルト設定なので、設定を変更していななければ「server.xml」は編集する必要はありません。
-- 「&link_anchor(tomcat-users.xml){tomcat-users.xml}」でユーザーとロールの設定

* web.xml
#highlight(){{
<?xml version="1.0" encoding="ISO-8859-1"?>
 
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0">

<!-- 管理画面の定義 -->
<security-constraint>
  <!-- URLのパターン設定 -->
  <web-resource-collection>
    <web-resource-name>admin page</web-resource-name> 
    <url-pattern>/admin/*</url-pattern> 
  </web-resource-collection>

  <!-- アクセスを許可するロールの設定 -->
  <auth-constraint>
    <role-name>admin</role-name> 
  </auth-constraint>

  <!-- 通信方式 NONE=ノーガード INTEGRAL=改竄防止(https) CONFIDENTIAL=盗聴防止(https) -->
  <user-data-constraint>
    <transport-guarantee>NONE</transport-guarantee> 
  </user-data-constraint>
</security-constraint>

<!-- 会員用コンテンツの定義 -->
<security-constraint>
  <web-resource-collection>
    <web-resource-name>users page</web-resource-name> 
    <url-pattern>/users/*</url-pattern> 
  </web-resource-collection>
  <auth-constraint>
    <role-name>user</role-name> 
  </auth-constraint>
  <user-data-constraint>
    <transport-guarantee>NONE</transport-guarantee> 
  </user-data-constraint>
</security-constraint>

<!-- 認証方法の定義 -->
<login-config>
  <!-- Basic認証 -->
  <auth-method>BASIC</auth-method> 
  <!-- 認証ダイアログに表示されるエリア名的な何か -->
  <realm-name>security area</realm-name>
</login-config>

</web-app>
}}
- 今回はサーブレットを作成していないので、認証設定だけのweb.xmlです。
- web.xmlでは主に、サーバクライアント間の認証方法と、アクセス制御するURLとロールの設定を行います。
- <security-constraint>で、URLのパターン設定(複数可)、アクセスを許可するロールの設定(複数可)、通信方式の設定をしています。
-- 「/admin/*」で、adminディレクトリ配下全てがアクセス制御の対象となります。
-- httpsの設定は今回行なっていないので、通信方式はNONEを選択しました。
- <login-config>で、認証方法とダイアログに表示されるエリア名を設定しています。
-- なんか微妙です。


** web.xml DIGEST認証の場合
#highlight(){{
<!-- 認証方法の定義 -->
<login-config>
  <!-- DIGEST認証 -->
  <auth-method>DIGEST</auth-method> 
  <!-- 認証ダイアログに表示されるエリア名的な何か -->
  <realm-name>security area</realm-name>
</login-config>
}}
- 上記web.xmlの設定の<login-config><auth-method>をDIGESTに変更するだけで、DIGEST認証を利用出来ます。
-- Tomcat7はここを変えるだけで利用出来ますが、Tomcat5はレルム方式をメモリレルムにしないとDIGEST認証を利用出来ないそうです。


* server.xmlの設定
(認証に関係のある要素を抜粋)※デフォルトなら編集不要
#highlight(){{
<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">

  <!-- JNDIリソースの設定 conf/tomcat-users.xmlを認証情報に利用します -->
  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

  <Service name="Catalina">

    <Engine name="Catalina" defaultHost="localhost">

      <!-- ブルートフォースアタック対策にLockOutRealmでラップします -->
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- 認証に利用するクラスとリソースを設定 -->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

    </Engine>
  </Service>
</Server>
}}
- server.xmlでは主に、サーバ内での認証情報(リソース)の取り扱いを設定します。
- 上記の設定はTomcat7インストール時のデフォルト設定です。
-- デフォルトでUserDatabaseRealmを利用する場合、server.xmlは編集不要です。
- 前段で「conf/tomcat-users.xml」からログインIDやパスワード等の認証に必要な情報を読取るJNDIリソースの設定。
- 後段で、リソースの指定と認証に使うクラスの指定に分かれています。
- ブルートフォースアタック対策のUserDatabaseRealmをブルートフォースアタック対策のLockOutRealmでラッピングしているのが印象的な設定です。


* tomcat-users.xml
#highlight(){{
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
  <role rolename="admin"/>
  <role rolename="user"/>
  <user username="admin" password="password1" roles="admin,user"/>
  <user username="user1" password="password2" roles="user"/>
</tomcat-users>
}}
- ロールは管理者用のadminロールと、会員用のuserロールを作成します。
- adminユーザーはadminロールとuserロール両方を設定。
- user1ユーザーはuserロールのみ設定します。
- 管理者を増やす時は、adminユーザーの設定をコピーしてusernameとpasswordをそれぞれ設定します。
- ユーザーを増やす時も同様に、user1ユーザーの設定をコピーしてusernameとpasswordをそれぞれ設定します。

* index.jsp サンプルダウンロード
&ref(BasicAuth.zip)
- サンプルをダウンロードして見てみてください。

&ref(BasicAuth01.png)
Tomcatを起動してブラウザでusersディレクトリやadminディレクトリにアクセスすると、上のようなユーザー名とパスワードの入力を求めるダイアログが表示されます。

user1でログインしてadminディレクトリにアクセスすると403エラーになり、adminユーザーでログインすると全てのリソースにアクセスできます。

* それぞれのユーザーのアクセス範囲
** ログインしてない人のアクセス出来る範囲
/CONTEXT_ROOT
┣ public
┃┗ index.html
┗ index.html
- ログインしてない人は、usersとadminディレクトリにはアクセス出来ません。
- ルートのindex.htmlとpublicディレクトリの公開コンテンツのみにアクセス可能です。

** 会員のアクセス出来る範囲
/CONTEXT_ROOT
┣ public
┃┗ index.html
┣ users
┃┗ index.html
┗ index.html
- ログインした会員は、adminディレクトリにはアクセス出来ません。
- 公開コンテンツに加え会員用のusersディレクトリにアクセスが可能です。

** 管理者のアクセス出来る範囲
/CONTEXT_ROOT
┣ public
┃┗ index.html
┣ users
┃┗ index.html
┣ admin
┃┗ index.html
┗ index.html
- ログインした管理者は、全てのリソースにアクセス出来ます。


* ファイルの配置
/CONTEXT_ROOT
┣ WEB-INF
┃┗ web.xml
┣ public
┃┗ index.html
┣ users
┃┗ index.html
┣ admin
┃┗ index.html
┗ index.html
- これらの他に、Tomcat自身の設定ファイルserver.xmlとtomcat-users.xmlも設定が必要です。


* 認証情報をサーブレットやJSPで取得する方法
- ユーザー名 - HttpServletRequest#getRemoteUser
- ロール - HttpServletRequest#isUserInRole("user")
-- ロールは直接ロールを取得する方法はなく、isUserInRoleでユーザーがそのロールを持っているかを確認します。

- サーブレットの場合
#highlight(){{
// ユーザー名
String user = req.getRemoteUser();
// ロール
boolean isAdmin = req.isUserInRole("admin");}}

- JSPの場合
#highlight(){{
// ユーザー名
String user = request.getRemoteUser();
// ロール
boolean isAdmin = request.isUserInRole("admin");}}
- Tomcat7で動作確認していた感じでは、認証の必要なURLでないとユーザー名とロールは取得出来ないようです。
- 認証の必要ないURLで認証情報を取り扱うには、セッション等に保存して置いたほうがいいかもしれません。

* アンケート(このページの情報はお役に立ちましたか?)
#tvote("役に立った[1]","役に立たない[0]","分かりにくい[4]","間違っている[0]")

* 他のTomcatサンプルはこちら
#inc(Java/Tomcat/サンプル)

* コメント(バグ、間違い、こんな情報が欲しい等ありましたら)
#pcomment(reply)