セキュリティ ガイド

     前  次    目次    
ここから内容

サードパーティのアプリケーションの保護

いくつかのポートレットは、ユーザ名とパスワードを使用してバックエンド システムまたはリモート アプリケーションに接続する必要があります。リモート アプリケーションは、ポータルが使用する同じ資格を使用しています。また、ポートレットはその資格を再使用できます。しかし、ほとんどの場合、リモート システムで必要となる資格は、ポータルにログインするために使用されるユーザ資格と同じではありません。最適なユーザ環境のため、シングル サインオンが必要です。Credential Vault は、リモート アプリケーションにアクセスするポートレット用の資格を安全に設定および取得するには、安全なストレージ メカニズムを提供します。

 


Credential Vault の概要

WebLogic Portal の以前のリリースでは、資格をユーザ プロファイルに格納することによって、Credential Vault のような機能を実装することができました。ただし、ユーザ プロファイル プロパティは暗号化されていないため、資格を格納するための安全な場所ではありません。WebLogic Server の暗号化メソッドを使用してプロパティを暗号化できますが、そのメソッドは複雑で限定的であり、カスタム プログラミングを必要とします。また、JCA アダプタがポートレットのスコープに適合しないため、JCA は使用できません。

Credential Vault は、ポートレットがユーザ資格を格納し、アクセスできる API を提供し、その資格を使用してユーザに代わってリモート アプリケーションにログインすることができます。これらの API では、開発者はユーザ名およびパスワードを格納する安全なリポジトリを構築したり、リソースに必要な任意のメタデータ (URL 等) を構築することができます。ユーザ名とパスワードは暗号化されていますが、メタデータ (String タイプの名前と値のペア) はプレーン テキストに格納されています。Credential Vault は、リモート システムに資格を渡すためのメカニズムを提供しません。

API の他に、Credential Vault はポータル管理者がシステムの Credential Vault を作成できる WebLogic Portal Administration Console で GUI を提供します。3 つのタイプの Credential Vault は、以下のとおりです。

User Credential Vault

User Credential Vault は、ユーザ名のみに基づく個々のポートレットのリモート システムに対してユーザの資格を安全に格納します。つまり、資格エントリはログイン ユーザのすべてのリソース インスタンスにアクセスできます。WebLogic Portal Javadoc では、このエントリは USER_TYPE と呼ばれています。

一般的な実装では Credential Vault API を使用して、ログインユーザがそれらのログイン情報をリモート システムに提供できるポートレットは作成できます。その後、ユーザがポータルにログインするときは、ポートレット コードは、自動的にログイン情報を読み込み、ユーザがそれらの資格を再度入力することなしにリモート アプリケーションに渡します。次の図は、Credential Vault のこのタイプの例を示しています。ここで、同じポータル ページでの 2 つのポートレットは 2 つの異なったリモート システムに接続します。

図 5-1 User Credential Vault

User Credential Vault

User + Resource Credential Vault

ポータルが、異なる資格を必要とするユーザに対し同じリモート システムに接続される 2 つまたは複数のポートレットを含む場合、このタイプの Credential Vault を使用してください。たとえば、1 つのポートレットはユーザを汎用ユーザとしてリモート システムに接続し、他のポートレットはユーザを管理者として接続する場合があります。User + Resource Credential Vault では、資格エントリは、ログイン ユーザの特定のリソース インスタンスのみにアクセスできます。WebLogic Portal Javadoc では、このエントリは RESOURCE_TYPE と呼ばれています。

図 5-2 User + Resource Credential Vault

User + Resource Credential Vault

System Credential Vault

管理者は、すべてのログイン ユーザの資格エントリがリソース インスタンスにアクセスできるように、グローバルなユーザ名とパスワードを格納する System Credential Vault を作成できます。WebLogic Portal Javadoc では、このエントリは SYSTEM_TYPE と呼ばれています。

このタイプの Credential Vault は、複数のユーザを同じパスワード (とユーザ名) を共有して、リモート リソースにアクセスすることができます。これは、デモンストレーション アカウントとして使用するために最適です。ユーザがアカウントを取得する前にリソースへの読み取りアクセスが可能です。System Credential Vault を作成するには、Credential Vault API か WebLogic Portal Administration Console のどちらかを使用できます。詳細については、「Credential Vault API の使用」および「Administration Console で System Credential の作成または表示」を参照してください。

表示

Web アプリケーション、エンタープライズ アプリケーション、およびドメイン内に渡り、3 つの Credential Vault エントリのスコープを指定できます。

スコープ指定は、Java EE アプリケーション内の Credential Vault の名前をシャドウすることを許可します。同じスコープ内で名前はユニークである必要があります。さまざまなスコープ内で名前をシャドウすることができます。外部スコープから、すべての名前はそれらを含むスコープに表示されます。たとえば、EAR スコープと WAR スコープの両方が foo という Credential Vault を持つ場合、WAR スコープ内の foo は EAR スコープ内の foo をシャドウするため、WAR スコープにある Credential Vault を使用します。

次の図に例を示します。

図 5-3 Credential Vault

Credential Vault

Credential Vault にアクセスする場合、ポートレットに関連付けられているコードはユーザのエントリを検索するまで Credential Vault をトラバースします。資格が検索されない場合、API を使用してユーザにログインを表示できます。次の例に詳細を示します。

従業員は WebLogic で認証されたユーザ名とパスワードを使用して人事部のポータル ページにログインします。このページでは、給与、株式オプションおよびキャリア開発などのサービスに対するポートレットが含まれています。従業員がリモート SAP アプリケーションにある賃金控除と給与システムを変更したいとします。従業員が給与ポートレットをクリックすると、システムは給与の Credential Vault (Web アプリケーション) でログイン資格を検索します。従業員の資格が見つかると、ポートレットは SAP 給与アプリケーションにユーザをログインします。

この Credential Vault に従業員の資格が存在しない場合、ポートレットは Enterprise Credential Vault (EAR) で検索します。Enterprise Credential Vault に従業員の資格が含まれている場合、ポートレットは SAP 給与アプリケーションに従業員をログインします。含まれていない場合は、システムは グローバルな Credential Vault (ドメイン) で資格を検索します。ポートレットが従業員の資格を見つけると、リモート SAP アプリケーションに従業員をログインします。見つからない場合、ポートレットは SAP アプリケーションへのログインを提供します。

ユーザが正常に SAP アプリケーションにログインされると、Credential Vault の 1 つに資格を格納します。この Credential Vault はシステム設定によって決定されます。

 


Credential Vault API の使用

Javadoc で説明されている「com.bea.p13n.security.management.credentials」パッケージは、エントリを作成し、Credential Vault の 3 つのタイプにアクセスするようにします。Javadoc は、Credential Vault を実装するために必要な詳細情報を提供します。以降の節では、Credential Vault の作成とアクセスの使用方法のためのフレームワークについて説明します。

注意 : 以下のいくつかの節では、Credential Vault のタイプの例として RESOURCE_TYPE (User + Resource) を使用します。タイプを変更するには、単に RESOURCE_TYPEUSER_TYPE か、SYSTEM_TYPE に変更します。

Credential Vault の初期化

Credential Vault Service インタフェースを通して、Credential Vault API へのエントリ ポイントがあります。

CredentailVaultService cvs = com.bea.wlp.services.Services.getService(com.bea.p13n.security.management.credentials.CredentailVaultService.class)

リソース キーの構成

リソース キーでは Credential Service のスコープとリソース ID が含まれています。ポートレット インスタンスは Web スコープ指定リソースですので、スコープを指定する必要があります。

ResourceKey rc = new ResourceKey(Scope.getWebApplicationScope(request), portletInstanceId);
ヒント : リソース ID は User Credential Vault または System Credential Vault に必須ではありませんが、実際のリソース ID を使用することがベスト プラクティスです。これにより、将来、容易に Credential Vault を別のタイプに変更できます。

資格エントリの作成

エントリを作成すると、Credential Vault のためにリソース キーとエントリ タイプを設定できます。エントリ タイプは以下のいずれかです。USER_TYPE (User)、RESOURCE_TYPE (User + Resource)、および SYSTEM_TYPE (System)

return cvs.createCredentialEntry(entryName, EntryType.RESOURCE_TYPE, null, rc);

以下のエントリの説明も提供できます。説明を必要としない場合、null を使用します。

資格エントリへのアクセス

エントリにアクセスする場合、Credential Vault に対してリソース キーとエントリ タイプを提供します。エントリ タイプは以下のいずれかである。USER_TYPE (User)、RESOURCE_TYPE (User + Resource)、および SYSTEM_TYPE (System)

return cvs.fetchCredentialEntry(entryName, EntryType.RESOURCE_TYPE, rc);
注意 : 複数のエントリが同じ名前で、異なるスコープで存在している場合、リソースが要求される最も近いスコープの 1 つが検索されます。

資格エントリの更新

ユーザ名とパスワードを追加または変更するには、UserPasswordCredential を使用します。

entry.setCredential(new UserPasswordCredential(username, password.getBytes("UTF-8")));

資格エントリの削除

資格エントリを削除するには、removeCredentialEntry を使用します。

cvs.removeCredentialEntry(entryName, EntryType.RESOURCE_TYPE, rc);

 


Credential Vault の例

各 Credential Vault に対する CRUD 操作を示すサンプル コードは、Oracle Technology Network Web サイトから入手できます。Credential Vault を検索します。

以下の例では、User (USER_TYPE) Credential Vault 用の CRUD 操作を示します。User + Resource Credential Vault および System Credential Vault のために、それぞれのタイプを RESOURCE_TYPE または SYSTEM_TYPE に変更する必要があります。

CredentialVaultHelper クラスは、Credential Vault API を使用するために必要となるすべてのコードを示しています。

コード リスト 5-1 CredentialHelper クラス
package examples.credential;
import javax.servlet.http.HttpServletRequest;
import com.bea.p13n.security.management.credentials.AlreadyExistsException;
import com.bea.p13n.security.management.credentials.CredentialVaultService;
import com.bea.p13n.security.management.credentials.ResourceKey;
import com.bea.p13n.security.management.credentials.Scope;
import com.bea.p13n.security.management.credentials.CredentialEntry;
import com.bea.p13n.security.management.credentials.CredentialEntry.EntryType;
public class CredentialHelper
{
   private static CredentialVaultService cvs = com.bea.wlp.services.Services.getService(CredentialVaultService.class);
   
   public static CredentialEntry createCredentialEntryForPortletInstance(String entryName, HttpServletRequest request)
      throws AlreadyExistsException
   {
      String portletInstanceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      //ポートレット インスタンスは Web スコープのリソースであるため、Web アプリケーション スコープが必要。
      ResourceKey rc = new ResourceKey(Scope.getWebApplicationScope(request), portletInstanceId);
      return cvs.createCredentialEntry(entryName, EntryType.RESOURCE_TYPE, null, rc);
   }
   public static CredentialEntry getCredentialEntryForPortletInstance(String entryName, HttpServletRequest request)
   {
      String portletInstanceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      // ポートレット インスタンスは Web スコープのリソースであるので、Web アプリケーション スコープが必要。
      ResourceKey rc = new ResourceKey(Scope.getWebApplicationScope(request), portletInstanceId);
      return cvs.fetchCredentialEntry(entryName, EntryType.RESOURCE_TYPE, rc);
   }
   
   public static void removeCredentialEntryForPortletInstance(String entryName, HttpServletRequest request)
   {
      String portletInstanceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      // ポートレット インスタンスは Web スコープのリソースであるため、Web アプリケーション スコープが必要。
      ResourceKey rc = new ResourceKey(Scope.getWebApplicationScope(request), portletInstanceId);
      cvs.removeCredentialEntry(entryName, EntryType.RESOURCE_TYPE, rc);
   }
   
   public static CredentialEntry createUserCredentialEntry(String entryName, HttpServletRequest request)
      throws AlreadyExistsException
   {
      // ユーザ資格タイプで resourceId が必要ではないので、何でも使用できます。
      String dummyResourceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      // この例はエンタープライズ スコープを使用するので、すべてのポータル Web にこのエントリを表示できますが、外部のユーザに対する他のエンタープライズ アプリケーションに表示できません。
      ResourceKey rc = new ResourceKey(Scope.getApplicationScope(), dummyResourceId);
      return cvs.createCredentialEntry(entryName, EntryType.USER_TYPE, null, rc);
   }
   public static CredentialEntry getUserCredentialEntry(String entryName, HttpServletRequest request)
   {
      //ユーザ資格タイプで resourceId が必要ではないので、何でも使用できます。
      String dummyResourceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      //この例はエンタープライズ スコープを使用するので、すべてのポータル Web にこのエントリを表示できますが、外部のユーザに対する他のエンタープライズ アプリケーションに表示できません。
      ResourceKey rc = new ResourceKey(Scope.getApplicationScope(), dummyResourceId);
      return cvs.fetchCredentialEntry(entryName, EntryType.USER_TYPE, rc);
   }
   public static void removeUserCredentialEntry(String entryName, HttpServletRequest request)
   {
      //ユーザ資格タイプで resourceId は重要ではないため、どれでも使用可能です。
      String dummyResourceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      //この例はエンタープライズ スコープを使用するので、すべてのポータル Web にこのエントリを表示できますが、外部のユーザに対する他のエンタープライズ アプリケーションには表示できません。
      ResourceKey rc = new ResourceKey(Scope.getApplicationScope(), dummyResourceId);
      cvs.removeCredentialEntry(entryName, EntryType.USER_TYPE, rc);
   }
   //ポータル管理者のみがシステム資格を作成する委託を持っています。
   public static CredentialEntry createCommonCredentialEntry(String entryName, HttpServletRequest request)
      throws AlreadyExistsException
   {
      //ユーザ資格タイプで resourceId は重要ではないため、どれでも使用可能です。
      String dummyResourceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      //この例はエンタープライズ スコープを使用するので、すべてのポータル Web にこのエントリを表示できますが、外部のユーザに対する他のエンタープライズ アプリケーションには表示できません。
      ResourceKey rc = new ResourceKey(Scope.getApplicationScope(), dummyResourceId);
      return cvs.createCredentialEntry(entryName, EntryType.SYSTEM_TYPE, null, rc);
   }
   public static CredentialEntry getCommonCredentialEntry(String entryName, HttpServletRequest request)
   {
      //ユーザ資格タイプで resourceId は重要ではないため、どれでも使用可能です。
      String dummyResourceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      //この例はエンタープライズ スコープを使用するので、すべてのポータル Web にこのエントリを表示できますが、外部のユーザに対する他のエンタープライズ アプリケーションには表示できません。
      ResourceKey rc = new ResourceKey(Scope.getApplicationScope(), dummyResourceId);
      return cvs.fetchCredentialEntry(entryName, EntryType.SYSTEM_TYPE, rc);
   }
   //ポータル管理者のみがシステム資格を作成する委託を持っています。
   public static void removeCommonCredentialEntry(String entryName, HttpServletRequest request)
   {
      //ユーザ資格タイプで resourceId は重要ではないため、どれでも使用可能です。
      String dummyResourceId = com.bea.netuix.util.PortalFrameworkUtils.getUniquePortletDesktopString(request);
      //この例はエンタープライズ スコープを使用するので、すべてのポータル Web にこのエントリを表示できますが、外部のユーザに対する他のエンタープライズ アプリケーションには表示できません。
      ResourceKey rc = new ResourceKey(Scope.getApplicationScope(), dummyResourceId);
      cvs.removeCredentialEntry(entryName, EntryType.SYSTEM_TYPE, rc);
   }
}

EmailAccountBacking ファイルは、User (USER_TYPE) Credential Vault ではエントリを取得および更新するために必要となるポートレット ロジックの例を示します。バッキング ファイルの詳細については、『ポートレット開発ガイド』の「バッキング ファイル」を参照してください。

コード リスト 5-2 EmailAccountBacking ファイル
package examples.credential;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.bea.netuix.servlets.controls.content.backing.AbstractJspBacking;
import com.bea.netuix.servlets.controls.portlet.backing.PortletBackingContext;
import com.bea.netuix.servlets.controls.window.WindowCapabilities;
import com.bea.p13n.security.management.credentials.AlreadyExistsException;
import com.bea.p13n.security.management.credentials.CredentialEntry;
import com.bea.p13n.security.management.credentials.UserPasswordCredential;
public class EmailAccountBacking extends AbstractJspBacking {
   private static final long serialVersionUID = -4933113295375846721L;
   
   private CredentialEntry entry;
   
   @Override
   public boolean handlePostbackData(HttpServletRequest request, HttpServletResponse response)
   {
      //Vault から資格エントリを取得。
      entry = CredentialHelper.getCredentialEntryForPortletInstance("emailAccount", request);
      
      if ( isRequestTargeted(request) )
      {
         //config ページから遷移した場合、送信したパラメータを取得。
         String server = request.getParameter("server");
         String protocol = request.getParameter("protocol");
         String username = request.getParameter("username");
         String password = request.getParameter("password");
         if ( username != null && password != null)
         {
            if ( entry == null )
            {
               //存在しない場合、新しい資格エントリを作成。
               try
               {
                  entry = CredentialHelper.createCredentialEntryForPortletInstance("emailAccount", request);
               }
               catch (AlreadyExistsException e)
               {
                  e.printStackTrace();
               }
            }
            //資格またはプロパティのリセットや更新
            try
            {
               entry.setCredential(new UserPasswordCredential(username, password.getBytes("UTF-8")));
               entry.setAttribute("server", server);
               entry.setAttribute("protocol", protocl);
            }
            catch (Exception e)
            {
               e.printStackTrace();
            }
         }
         else if (request.getParameter("delete") != null)
         {
            //資格を削除してコンフィグレーション ぺージに戻る
            CredentialHelper.removeCredentialEntryForPortletInstance("emailAccount", request);
            PortletBackingContext.getPortletBackingContext(request).setupModeChangeEvent(WindowCapabilities.EDIT.getName());
            return true;
         }
         return false;
      }
      
      if ( entry == null )
      {
         //資格は設定されていない。コンフィグレーション ページに戻る。
         PortletBackingContext.getPortletBackingContext(request).setupModeChangeEvent(WindowCapabilities.EDIT.getName());
         return true;
      }
      else if ( ! WindowCapabilities.VIEW.equals(PortletBackingContext.getPortletBackingContext(request).getWindowMode()) )
      {
         PortletBackingContext.getPortletBackingContext(request).setupModeChangeEvent(WindowCapabilities.VIEW.getName());
         return true;
      }
      
      return false;
   }
   
   @Override
   public boolean preRender(HttpServletRequest request, HttpServletResponse response)
   {
      //ログインしたユーザに対してのみポートレットを表示。
      if ( request.getUserPrincipal() == null )
         return false;
      return true;
   }
}

index.jsp では、電子メール アカウントの資格エントリを示します。

コード リスト 5-3 Credential Vault index.jsp
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib uri="http://www.bea.com/servers/portal/tags/netuix/render" prefix="render" %>
<%@page import="com.bea.p13n.security.management.credentials.UserPasswordCredential" %>
<%@page import="com.bea.p13n.security.management.credentials.CredentialEntry" %>
<%@page import="examples.credential.CredentialHelper" %>
<%
   CredentialEntry entry = CredentialHelper.getCredentialEntryForPortletInstance("emailAccount", request);
   if (entry == null)
   {
      out.println("Credential not exists. Click edit button on right of portlet title bar to config credential");
   }
   else
   {
      UserPasswordCredential credential = (UserPasswordCredential)entry.getCredential();
%>
Email account for this portlet instance is:
<form method="post" action="<render:windowUrl/>">
<table>
   <tr>
      <td>mail server: </td>
      <td><%=entry.getAttribute("server")%>
   </tr>
   <tr>
      <td>protocol: </td>
      <td><%=entry.getAttribute("protocol")%>
   </tr>
   <tr>
      <td>username: </td>
      <td><%=credential.getPrincipalName()%>
   </tr>
   <tr>
      <td>password: </td>
      <td><%=new String(credential.getPrincipalPassword(), "UTF-8")%>
   </tr>
   <tr>
      <td colspan="2" align="center">
         <input type="hidden" name="delete" value="1">
         <input type="submit" value="delete"/>
      </td>
   </tr>
</table>
</form>
<%
   }
%>

config.jsp は電子メール アカウントの資格エントリを更新します。

コード リスト 5-4 Credential Vault config.jsp
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib uri="http://www.bea.com/servers/portal/tags/netuix/render" prefix="render" %>
<%@ page import="com.bea.netuix.servlets.controls.window.WindowCapabilities" %>
<form method="post" action="<render:windowUrl windowMode='<%=WindowCapabilities.VIEW.getName()%>'/>">
Note: do not leave field empty, this simple demo does not validate input.<br/>
Otherwise, a NPE exception may appear.
<table>
   <tr>
      <td>mail server: </td>
      <td><input type="text" name="server"/>
   </tr>
   <tr>
      <td>protocol: </td>
      <td><input type="text" name="protocol" />
   </tr>
   <tr>
      <td>username: </td>
      <td><input type="text" name="username" />
   </tr>
   <tr>
      <td>password: </td>
      <td><input type="password" name="password" />
   </tr>
   <tr>
      <td colspan="2" align="center"><input type="submit" value="save"/></td>
   </tr>
</table>
</form>

 


Administration Console で System Credential の作成または表示

WebLogic Portal Administration Console により、管理者に対して System Credential Vault の作成権限が提供されます。System Credential Vault で説明しているように、System Credential Vault はグローバルのユーザ名およびパスワード用の Vault です。

注意 : Portal Administration console を使用して System Credential Vault を作成する場合、同じドメインで異なるエンタープライズ アプリケーションにはエントリが表示されないエンタープライズ アプリケーション スコープの Credential Vault を作成します。

System Credentials を表示するには、

  1. Administration Console を起動します。
  2. [コンフィグレーションとモニタ|サービス管理] を選択します。
  3. リソース ツリーで [セキュリティ|Credential Vault] を選択します。
  4. 図 5-4 Credential Vault


    Credential Vault

  5. 新しい資格を作成するには、[新しい資格の作成] をクリックします。
  6. 表 5-1 にあるように値を指定します。
    表 5-1 System Credential
    資格名
    システム資格の名
    説明
    資格の省略可能な説明
    ユーザ名
    ポータル管理者の名
    パスワード
    リソースにアクセスするパスワード
    パスワード (再入力)
    リソース パスワードの確認
    メタデータ名と値のペア
    外部システムに必要となるメタデータおよびすべてのデータの名 (URL やディレクトリ パスなど)。
  7. 追加のメタデータを入力するには、[別の値の追加] をクリックします。
  8. [保存] をクリックします。

  ページの先頭       前  次