第2章 セキュリティーの概要

2.1. 宣言的セキュリティー

宣言的セキュリティー とは、セキュリティー管理にコンテナを使うことで、お使いのアプリケーションコードからセキュリティーの問題を切り離す方法です。コンテナにより、ファイルのパーミッション、またはユーザー、グループ、ロールに基づき承認を行います。このアプローチは、セキュリティー関連すべてをアプリケーション自体で請け負うプログラム的セキュリティーよりも優れています。
JBoss EAP 6 はセキュリティードメインより宣言的セキュリティーを提供します。

2.1.1. Java EE 宣言型セキュリティーの概要

J2EE セキュリティーモデルは宣言的で、セキュリティーをビジネスコンポーネントに埋め込まずに、セキュリティーロールおよびパーミッションを標準的な XML 記述子で記述します。セキュリティーは、コンポーネントのビジネスロジックに固有のものではなく、コンポーネントがデプロイされる場所の機能となる傾向にあるため、このモデルによりセキュリティーがビジネスレベルコードより隔離されます。たとえば、銀行の預金口座を利用するために使用する ATM の場合、預金口座へのアクセス方法、口座を管理する銀行、ATM の場所などの条件によって、セキュリティー要件、ロール、およびパーミッションが大きく異なります。
J2EE アプリケーションは、標準の J2EE デプロイメント記述子によって指定されたアプリケーションセキュリティー要件を基にセキュア化されます。ejb-jar.xml および web.xml デプロイメント記述子を使用して、エンタープライズアプリケーションの EJB および Web コンポーネントへのアクセスをセキュア化します。

2.1.2. セキュリティーの参照

Enterprise Java Bean (EJB) およびサーブレットは、1 つまたは複数の <security-role-ref> 要素を宣言できます。
セキュリティーロール参照モデル図

図2.1 セキュリティーロール参照モデル

この要素は、コンポーネントが <role-name> 要素の role-nameType 属性値を isCallerInRole(String) メソッドへの引数として使用することを宣言します。isCallerInRole メソッドを使用すると、コンポーネントは <security-role-ref> または <role-name> 要素で宣言されたロールに呼び出し元があるかどうかを検証できます。<role-name> 要素の値は、<role-link> 要素を介して <security-role> へリンクする必要があります。通常、isCallerInRole は、ロールベースの <method-permissions> 要素を使用して定義できないセキュリティーチェックを実行するために使用されます。

例2.1 ejb-jar.xml 記述子の一部

  
  <!-- A sample ejb-jar.xml fragment -->
    <ejb-jar>
      <enterprise-beans>
        <session>
          <ejb-name>ASessionBean</ejb-name>
          ...
          <security-role-ref>
            <role-name>TheRoleICheck<role-name>
              <role-link>TheApplicationRole</role-link>
          </security-role-ref>
        </session>
      </enterprise-beans>
    ...
    </ejb-jar>

注記

これは実例ではありません。デプロイメントでは、このセクションの要素に EJB デプロイメントに関連するロール名およびリンクが含まれている必要があります。

例2.2 web.xml 記述子の一部


<web-app>
  <servlet>
    <servlet-name>AServlet</servlet-name>
    ...
    <security-role-ref>
      <role-name>TheServletRole</role-name>
      <role-link>TheApplicationRole</role-link>
    </security-role-ref>
  </servlet>
    ...
</web-app>

2.1.3. セキュリティーアイデンティティー (ID)

Enterprise Java Bean (EJB) は、<security-identity> 要素を使用してコンポーネント上でメソッドを呼び出すときに使用する必要がある、別の EJB の ID を指定できます。
J2EE セキュリティーアイデンティティーデータモデル図

図2.2 J2EE セキュリティーアイデンティティーデータモデル

呼び出し ID は現在の呼び出し元の ID、または特定のロールを指定できます。アプリケーションアセンブラーは、<security-identity> 要素と <use-caller-identity> 子要素を使用します。そのため、現在の呼び出し元の ID は、EJB によって実行されたメソッド呼び出しのセキュリティー IDとして伝播される必要があります。呼び出し元の ID の伝播は、<security-identity> 要素が明示的に宣言されていない場合に使用されるデフォルトの動作です。
また、アプリケーションアセンブラーで <run-as> または <role-name> 子要素を使用して、<role-name> 要素値によって提供される特定のセキュリティーロールが、EJB によって実行されたメソッド呼び出しのセキュリティー ID として使用されるように指定することも可能です。
EJBContext.getCallerPrincipal() メソッドのように呼び出し元の ID が変更されないことに注意してください。呼び出し元のセキュリティーロールは、<run-as> または <role-name> 要素値によって指定された単一のロールに設定されます。
<run-as> 要素を使用すると、外部クライアントによる内部 EJB へのアクセスを防ぐことができます。この挙動を設定するには、内部 EJB の <method-permission> 要素を割り当てます。この要素は、外部クライアントへ割り当てられていないロールへのアクセスを制限します。この後、内部 EJB を使用しなければならない EJB は、<run-as> または <role-name> が制限されたロールと同等として設定されます。以下の記述子の断片は、<security-identity> 要素の使用例を記述します。

<ejb-jar>
    <enterprise-beans>
        <session>
            <ejb-name>ASessionBean</ejb-name>
            <!-- ... -->
            <security-identity>
                <use-caller-identity/>
            </security-identity>
        </session>
        <session>
            <ejb-name>RunAsBean</ejb-name>
            <!-- ... -->
            <security-identity>
                <run-as>
                    <description>A private internal role</description>
                    <role-name>InternalRole</role-name>
                </run-as>
            </security-identity>
        </session>
    </enterprise-beans>
    <!-- ... -->
</ejb-jar>

<run-as> を使用して特定のロールを発信呼び出しへ割り当てると、anonymous という名前のプリンシパルがすべての発信呼び出しへ割り当てられます。別のプリンシパルを呼び出しに関連付けるには、<run-as-principal>jboss.xml ファイルの Bean に関連付けます。以下の断片は、internal という名前のプリンシパルを前例の RunAsBean に関連付けます。

<session>
    <ejb-name>RunAsBean</ejb-name>
    <security-identity>
        <run-as-principal>internal</run-as-principal>
    </security-identity>
</session>

<run-as> 要素は、web.xml ファイルのサーブレット定義にもあります。以下の例は、InternalRole ロールをサーブレットに割り当てる方法を示しています。

  <servlet>
    <servlet-name>AServlet</servlet-name>
    <!-- ... -->
    <run-as> 
        <role-name>InternalRole</role-name>
    </run-as>
  </servlet>

このサーブレットからの呼び出しは、匿名の principal に関連付けられます。run-as ロールに従う特定のプリンシパルを割り当てるため、<run-as-principal> 要素は jboss-web.xml ファイルにあります。以下の断片は、internal という名前のプリンシパルを上記のサーブレットに関連付ける方法を示しています。

  <servlet>
    <servlet-name>AServlet</servlet-name>
    <run-as-principal>internal</run-as-principal>
  </servlet>

2.1.4. セキュリティーロール

security-role-ref または security-identity 要素によって参照されるセキュリティーロール名は、アプリケーションの宣言済みロールの 1 つへマップする必要があります。アプリケーションアセンブラーは、security-role 要素を宣言して論理セキュリティーロールを定義します。role-name の値は、論理アプリケーションロール名になります (Administrator、Architect、SalesManager など)。
J2EE 仕様には、デプロイメント記述子のセキュリティーロールはアプリケーションの論理セキュリティービューを定義するために使用されることを考慮することが重要であると記載されています。J2EE デプロイメント記述子に定義されるロールを、ユーザーグループ、ユーザー、プリンシパル、および目的企業の操作環境に存在するその他の概念と混同してはなりません。デプロイメント記述子ロールは、アプリケーションドメイン固有の名前を持つアプリケーションコンストラクトです。たとえば、銀行取引のアプリケーションでは BankManager、Teller、Customer などをロール名として使用することがあります。
JBoss EAP では、security-role 要素は security-role-ref/role-name の値をコンポーネントロールが参照する論理ロールへマップためだけに使用されます。ユーザーの割り当てられたロールは、アプリケーションのセキュリティーマネージャーの動的関数です。JBoss では、メソッドパーミッションの宣言に security-role の定義は必要ありません。しかし、アプリケーションサーバーにまたがる移植性を維持し、デプロイメント記述子を保持するため、security-role 要素を指定することが推奨されます。

例2.3 security-role 要素の使用を示す ejb-jar.xml 記述子の断片

<!-- A sample ejb-jar.xml fragment --><ejb-jar><assembly-descriptor><security-role><description>The single application role</description><role-name>TheApplicationRole</role-name></security-role></assembly-descriptor></ejb-jar>

    
        
            
            
        
    

例2.4 security-role 要素の使用を示す web.xml 記述子の断片の例

<!-- A sample web.xml fragment --><web-app><security-role><description>The single application role</description><role-name>TheApplicationRole</role-name></security-role></web-app>

  
    
    
  

2.1.5. EJB メソッドのパーミッション

アプリケーションアセンブラーは、method-permission 要素を宣言して EJB のホームおよびリモートインターフェースメソッドを呼び出せるロールを設定できます。
J2EE メソッドパーミッション要素の図

図2.3 J2EE メソッドパーミッション要素

method-permission 要素には、メソッド子要素によって特定された EJB メソッドへアクセスできる論理ロールを定義する 1 つ以上の role-name 子要素が含まれています。また、role-name 要素の代わりに unchecked 要素を指定して、認証されたすべてのユーザーがメソッド子要素によって特定されたメソッドにアクセスできることを宣言できます。さらに、exclude-list 要素があるメソッドにはアクセスできないことを宣言することも可能です。method-permission 要素を使用して、ロールによるアクセスが可能であると宣言されていないメソッドが EJB にある場合、EJB メソッドはデフォルトでは使用されません。これは、メソッドがデフォルトで exclude-list に含まれるようにすることと同じです。
J2EE メソッド要素の図

図2.4 J2EE メソッド要素

メソッド要素宣言のサポートされるスタイルは 3 つあります。
1 つ目のスタイルは、名前付きエンタープライズ Bean のホームおよびコンポーネントインターフェースメソッドをすべて参照するために使用されます。
<method><ejb-name>EJBNAME</ejb-name><method-name>*</method-name></method>
  
  

2 つ目のスタイルは、名前付きエンタープライズ Bean のホームまたはコンポーネントインターフェースの指定されたメソッドを参照するために使用されます。
  <method><ejb-name>EJBNAME</ejb-name><method-name>METHOD</method-name></method>
    
    

同じオーバーロードされた名前を持つ複数のメソッドがある場合、このスタイルはすべてのオーバーロードされたメソッドを参照します。
3 つ目のスタイルは、オーバーロードされた名前を持つメソッドのセット内で指定されたメソッドを参照するために使用されます。
<method><ejb-name>EJBNAME</ejb-name><method-name>METHOD</method-name><method-params><method-param>PARAMETER_1</method-param><!-- ... --><method-param>PARAMETER_N</method-param></method-params></method>
    
    
    
        
        
        
    

メソッドは指定されたエンタープライズ Bean のホームまたはリモートインターフェースに定義する必要があります。method-param 要素の値は、対応するメソッドパラメータータイプの完全修飾名です。同じオーバーロードされたシグネチャーを持つメソッドが複数ある場合、パーミッションは一致するオーバーロードされたメソッドすべてに適用されます。
任意の method-intf 要素は、エンタープライズ Bean のホームおよびリモートインターフェースの両方に定義された同じ名前やシグネチャーを持つメソッドを区別するために使用されます。
method-permission 要素の完全な使用例は、例2.5「method-permission 要素の使用を説明する ejb-jar.xml 記述子の断片」 を参照してください。

例2.5 method-permission 要素の使用を説明する ejb-jar.xml 記述子の断片

<ejb-jar><assembly-descriptor><method-permission><description>The employee and temp-employee roles may access any
                method of the EmployeeService bean </description><role-name>employee</role-name><role-name>temp-employee</role-name><method><ejb-name>EmployeeService</ejb-name><method-name>*</method-name></method></method-permission><method-permission><description>The employee role may access the findByPrimaryKey,
                getEmployeeInfo, and the updateEmployeeInfo(String) method of
                the AardvarkPayroll bean </description><role-name>employee</role-name><method><ejb-name>AardvarkPayroll</ejb-name><method-name>findByPrimaryKey</method-name></method><method><ejb-name>AardvarkPayroll</ejb-name><method-name>getEmployeeInfo</method-name></method><method><ejb-name>AardvarkPayroll</ejb-name><method-name>updateEmployeeInfo</method-name><method-params><method-param>java.lang.String</method-param></method-params></method></method-permission><method-permission><description>The admin role may access any method of the
                EmployeeServiceAdmin bean </description><role-name>admin</role-name><method><ejb-name>EmployeeServiceAdmin</ejb-name><method-name>*</method-name></method></method-permission><method-permission><description>Any authenticated user may access any method of the
                EmployeeServiceHelp bean</description><unchecked/><method><ejb-name>EmployeeServiceHelp</ejb-name><method-name>*</method-name></method></method-permission><exclude-list><description>No fireTheCTO methods of the EmployeeFiring bean may be
                used in this deployment</description><method><ejb-name>EmployeeFiring</ejb-name><method-name>fireTheCTO</method-name></method></exclude-list></assembly-descriptor></ejb-jar>
    
        
            
            
            
            
                
                
            
        
        
            
            
            
                
                
            
            
                
                
            
            
                
                
                
                    
                
            
        
        
            
            
            
                
                
            
        
        
            
            
            
                
                
            
        
        
            
            
                
                
            
        
    

2.1.6. エンタープライズ Bean セキュリティーアノテーション

エンタープライズ Bean はアノテーションを使用し、アプリケーションのセキュリティーやその他の情報をデプロイヤーへ渡します。アノテーションまたはデプロイメント記述子に指定された場合、デプロイヤーはアプリケーションに対して適切なエンタープライズ Bean セキュリティーポリシーを設定できます。
アノテーションの値は、デプロイメント記述子に明示的に指定されたメソッドの値によって上書きされます。メソッドの値がデプロイメント記述子に指定されていない場合、アノテーションを使用して設定された値が使用されます。粒度の上書きはメソッドごとに行われます。
セキュリティーに対応し、エンタープライズ Bean で使用できるアノテーションには以下が含まれます。
@DeclareRoles
コードに宣言された各セキュリティーロールを宣言します。ロールの設定に関する詳細情報は、『Java EE 5 Tutorial』 の Declaring Security Roles Using Annotations を参照してください。
@RolesAllowed@PermitAll、および @DenyAll
アノテーションのメソッドパーミッションを指定します。アノテーションメソッドパーミッションの設定に関する詳細は、『Java EE 5 Tutorial』 の Specifying Method Permissions Using Annotations を参照してください。
@RunAs
コンポーネントの伝播されたセキュリティーアイデンティティーを設定します。伝播されたセキュリティーアイデンティティーをアノテーションを使用して設定する方法については、『Java EE 5 Tutorial』 の Configuring a Component’s Propagated Security Identity を参照してください。

2.1.7. Web コンテンツのセキュリティー制約

Web アプリケーションでは、保護されたコンテンツを識別する URL パターンよりコンテンツへのアクセスが許可されるロールによってセキュリティーが定義されます。この情報セットは、web.xml security-constraint 要素を使用して宣言されます。
Web コンテンツのセキュリティー制約の図

図2.5 Web コンテンツのセキュリティー制約

セキュア化するコンテンツは、1 つ以上の <web-resource-collection> 要素を使用して宣言されます。各 <web-resource-collection> 要素には、任意の <url-pattern> 要素群と、これに続く任意の <http-method> 要素群が含まれます。<url-pattern> 要素の値は、リクエストがセキュア化されたコンテンツへのアクセスに対応するため、リクエスト URL が一致しなければならない URL パターンを指定します。<http-method> 要素の値は、許可する HTTP リクエストのタイプを指定します。
任意の <user-data-constraint> 要素は、クライアントサーバー接続のトランスポート層の要件を指定します。要件は、コンテンツの整合性 (通信プロセスでのデータ改ざんを防ぐ) または機密性 (送信中の読み取りを防ぐ) に関係することがあります。<transport-guarantee> 要素の値は、クライアントとサーバー間の通信に対する保護レベルを指定します。値は NONEINTEGRAL、および CONFIDENTIAL になります。NONE を指定すると、アプリケーションはトランスポートの保証を必要としません。INTEGRAL の場合、アプリケーションはクライアントとサーバー間での送信中でデータが変更されない方法を必要とします。CONFIDENTIAL の場合、アプリケーションは送信中のデータが他のエンティティーによって見られないようにする方法を必要とします。ほとんどの場合で、INTEGRAL または CONFIDENTIAL フラグが存在すると SSL の使用が必要になります。
任意の <login-config> 要素は、使用される認証メソッド、アプリケーションに使用されるレルム名、およびフォームログインのメカニズムに必要な属性を設定するために使用されます。
Web ログイン設定の図

図2.6 Web ログインの設定

<auth-method> 子要素は、Web アプリケーションの認証メカニズムを指定します。承認制約によって保護された Web リソースへアクセスするには、設定されたメカニズムを使用してユーザーが認証されている必要があります。<auth-method> の有効な値は、 BASICDIGESTFORM、および CLIENT-CERT です。<realm-name> 子要素は、HTTP ベーシックおよびダイジェスト認証で使用されるレルム名を指定します。<form-login-config> 子要素は、フォームベースのログインで使用されるログインおよびエラーページを指定します。<auth-method> 値が FORM でない場合、form-login-config と子要素は無視されます。
以下の設定例は、Web アプリケーションの /restricted パス下にある URL には /restricted ロールが必要であることを示しています。トランスポート保証は必要なく、ユーザーアイデンティティーの取得に使用される認証メソッドは BASIC HTTP 認証です。

例2.6 web.xml 記述子の断片

<web-app>
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Secure Content</web-resource-name>
            <url-pattern>/restricted/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>AuthorizedUser</role-name>
        </auth-constraint>
        <user-data-constraint>
            <transport-guarantee>NONE</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
    <!-- ... -->
    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>The Restricted Zone</realm-name>
    </login-config>
    <!-- ... -->
    <security-role>
        <description>The role required to access restricted content </description>
        <role-name>AuthorizedUser</role-name>
    </security-role>
</web-app>

2.1.8. フォームベース認証の有効化

フォームベース認証では、ログインのカスタム JSP/HTML ページや、ログイン中にエラーが発生した場合にユーザーが移動される別のページを柔軟に定義できます。
フォームベースの認証を定義するには、デプロイメント記述子 web.xml<login-config> 要素に <auth-method>FORM</auth-method> が含まれるようにします。ログインおよびエラーページも、以下のように <login-config> に定義されます。
<login-config>
  <auth-method>FORM</auth-method>
  <form-login-config>
    <form-login-page>/login.html</form-login-page>
    <form-error-page>/error.html</form-error-page>
  </form-login-config>
</login-config>
フォームベース認証の Web アプリケーションがデプロイされると、Web コンテナは FormAuthenticator を使用してユーザーを適切なページに移動します。JBoss EAP はセッションプールを保持するため、リクエストごとに認証情報が存在する必要はありません。FormAuthenticator がリクエストを受け取ると、既存のセッションに関して org.apache.catalina.session.Manager をクエリします。セッションが存在しない場合、新しいセッションが作成されます。その後、FormAuthenticator がセッションのクレデンシャルを検証します。

注記

各セッションは、セッション ID によって識別されます。セッション ID は、乱数値から生成された 16 バイトの文字列です。これらの値はデフォルトでは /dev/urandom (Linux の場合) より取得され、MD5 でハッシュ化されます。セッション ID は作成時にチェックされ、作成された ID が一意になるようにします。
検証後、セッション ID はクッキーの一部として割り当てられ、クライアントに返されます。後続のクライアントリクエストではクッキーがあることが想定され、ユーザーセッションの識別に使用されます。
クライアントへ渡されるクッキーは、名前と値のペアで、任意の属性が複数含まれています。識別子属性は JSESSIONID と呼ばれ、値はセッション ID の 16 進数列です。このクッキーは、非永続として設定されます。そのため、ブラウザーを終了するとクライアント側でこのクッキーが削除されます。サーバー側では、活動がないと 60 秒後にセッションが期限切れになり、セッションオブジェクトとそれらのクレデンシャルが削除されます。
ユーザーがフォームベースの認証で保護された Web アプリケーションにアクセスしようとすると、FormAuthenticator によってリクエストがキャッシュされ、必要な場合は新しいセッションが作成されます。さらに、ユーザーは login-config に定義されたログインページへリダイレクトされます (前述のコード例では、ログインページは login.html になります)。その後、ユーザーは提供される HTML フォームにユーザー名とパスワードを入力します。ユーザー名とパスワードは、j_security_check フォームアクションを介して FormAuthenticator へ渡されます。
次に、FormAuthenticator によって、ユーザー名とパスワードが Web アプリケーションコンテキストにアタッチされるレルムに対して認証されます。JBoss Enterprise Application Platform では、レルムは JBossWebRealm になります。認証に成功すると、FormAuthenticator によってキャッシュから保存されたリクエストが読み出され、ユーザーが元のリクエストへリダイレクトされます。

注記

サーバーは、URI が /j_security_check で終わり、最低でも j_username および j_password パラメーターが存在する場合のみ、フォーム認証リクエストを認識します。

2.1.9. 宣言型セキュリティーの有効化

これまで取り上げた Java EE セキュリティー要素は、アプリケーションの視点のみからセキュリティー要件を記述します。Java EE セキュリティー要素は論理ルールを宣言するため、アプリケーションデプロイヤーはロールをアプリケーションドメインからデプロイメント環境へマップします。Java EE 仕様は、このようなアプリケーションサーバー固有の詳細を省略します。
アプリケーションロールをデプロイメント環境にマップするには、JBoss EAP 固有のデプロイメント記述子を使用して Java EE セキュリティーモデルを実装するセキュリティーマネージャーを指定する必要があります。このセキュリティー設定の詳細は、カスタムログインモジュールの例を参照してください。