ヘッダーをスキップ
Oracle Database JDBC開発者ガイド
11gリリース2(11.2)
B56281-01
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

10 プロキシ認証

Oracle Java Database Connectivity(JDBC)は、n層認証とも呼ばれるプロキシ認証を提供しています。この機能は、JDBC Oracle Call Interface(OCI)ドライバとJDBC Thinドライバの両方を介してサポートされています。この章の内容は次のとおりです。


注意:

Oracle Databaseはプロキシ認証機能を3つの層のみでサポートしています。複数の中間層を横断してのサポートはありません。

プロキシ認証について

プロキシ認証はユーザー認証に中間層を使用する処理です。次の3つの形式のプロキシ認証を使用することによって、クライアントのセキュアなプロキシとして動作する中間層サーバーを設計することができます。

すべての場合で、クライアントのプロキシ(代理)として動作するために、管理者は中間層サーバーを認証する必要があります。たとえば、中間層サーバーが最初にユーザーscottとしてデータベースに接続し、プロキシ接続をユーザーjeffとしてアクティブにしてから、次の文を発行して、クライアントのプロキシとして動作するように中間層サーバーを認証するとします。

ALTER USER jeff GRANT CONNECT THROUGH scott;

また、次のことも可能です。


注意:

この章では、データベースへのJDBC接続はデータベース内のユーザー・セッションであり、その逆の場合もあります。

各種のプロキシ接続を設定するには、oracle.jdbc.OracleConnectionインタフェースにある、各種のフィールドやメソッドを使用する必要があります。

各種のプロキシ接続

プロキシ接続は、次のいずれかのオプションを使用して作成できます。


注意:

  • すべてのオプションは、ロールと関連付けることができます。

  • プロキシとしての役割を果す新しい接続をオープンすると、新しいセッションがデータベース・サーバー上で開始されます。このセッションとともに、新しいローカル・トランザクションが作成されます。


プロキシ接続の作成

ユーザー(たとえば、jeff)は、別のユーザー(たとえば、scott)を介してデータベースに接続する必要があります。プロキシ・ユーザーscottには、アクティブな認証済接続が必要です。ドライバがサーバーにコマンドを送信してユーザーjeffのセッションを作成することで、このアクティブな接続上にプロキシ・セッションが作成されます。サーバーは新しいセッションIDを戻し、ドライバはセッション切替えコマンドを送信してこの新しいセッションに切り替えます。

JDBC OCIとThinドライバは、同じ方法でセッションを切り替えます。ドライバは、永続的に新しいセッションjeffに切り替えます。その結果、プロキシ・セッションscottは、新しいセッションjeffがクローズされるまで使用できません。


注意:

oracle.jdbc.OracleConnectionインタフェースからisProxySessionメソッドを使用して、接続に関連付けられている現在のセッションがプロキシ・セッションであるかどうかをチェックすることができます。接続に関連付けられている現在のセッションがプロキシ・セッションの場合、このメソッドはtrueを戻します。

oracle.jdbc.OracleConnectionインタフェースから、次のメソッドを使用することで、新しいプロキシ・セッションが開かれます。

void openProxySession(int type, java.util.Properties prop) throws SQLExceptionOpens

ここで、

typeはプロキシ・セッションのタイプで、次の値を指定できます。

propはプロキシ・セッションのプロパティ値で、次の値を指定できます。

次のコードは、openProxySessionメソッドの使用方法を示します。

    java.util.Properties prop = new java.util.Properties();
    prop.put(OracleConnection.PROXY_USER_NAME, "jeff");
    String[] roles = {"role1", "role2"};
    prop.put(OracleConnection.PROXY_ROLES, roles);
    conn.openProxySession(OracleConnection.PROXYTYPE_USER_NAME, prop);
    

プロキシ・セッションのクローズ

OracleConnection.closeメソッドにOracleConnection.PROXY_SESSIONパラメータを渡すことによって、OracleConnection.openProxySessionメソッドでオープンしたプロキシ・セッションをクローズするには、次の操作を行います。

OracleConnection.close(OracleConnection.PROXY_SESSION);

これは、キャッシュされていない接続でのプロキシ・セッションのクローズと同じです。接続自体をクローズするには、標準のcloseメソッドを明示的にコールする必要があります。プロキシ・セッションをクローズせずにcloseメソッドを直接コールすると、プロキシ・セッションと接続の両方がクローズします。その方法は次のとおりです。

OracleConnection.close(OracleConnection.INVALID_CONNECTION);

プロキシ接続のキャッシュ

プロキシ接続は、通常の接続と同様にキャッシュできます。プロキシ接続をキャッシュすると、パフォーマンスが向上します。プロキシ接続をキャッシュするには、getConnectionメソッドのいずれかを使用して、キャッシュ対応のOracleDataSourceオブジェクトで接続を作成する必要があります。

プロキシ接続は、接続キャッシュの接続属性機能を使用して、接続キャッシュ内にキャッシュできます。接続属性はユーザー定義の名前/値ペアで、接続を接続キャッシュに戻して再利用する前に接続にタグを付けるのに役立ちます。タグ付けされた接続が取得されると、その接続を直接使用してプロキシ・セッションを作成またはクローズできるため、ラウンドトリップは必要ありません。暗黙的接続キャッシュは、すべてのユーザー/パスワード認証接続のキャッシュをサポートします。したがって、ユーザー認証のすべてのプロキシ接続はキャッシュおよび取得できます。

接続属性を適用せずにプロキシ接続をクローズすることはお薦めしません。接続属性を適用せずにプロキシ接続をクローズすると、その接続は再利用のために接続キャッシュに戻されますが取得できません。接続キャッシュ・メカニズムでは、セッション状態を記憶したりリセットしたりしません。

プロキシ接続は、直接クローズすることで、接続キャッシュから削除できます。

プロキシ接続の制限

プロキシ接続をクローズすると、プロキシ・セッション中またはプロキシ・セッションより前にプロキシ接続によって作成されたすべてのSQL文が自動的にクローズされます。これがアプリケーション・プーリングまたは文キャッシュに予期しない結果を招く可能性があります。次のサンプル・コードは、プロキシ接続のこの制限について説明しています。

例1

....
public void displayName(String N)  // Any function using the Proxy feature
{
     Properties props = new Properties();
     props.put("PROXY_USER_NAME", proxyUser);
     c.openProxySession(OracleConnection.PROXYTYPE_USER_NAME, props);
     .......
     c.close(OracleConnection.PROXY_SESSION);
}
 
public static void main (String args[]) throws SQLException
{
    ............
    PreparedStatement pstmt = conn.prepareStatement("SELECT empname FROM EMP WHERE empno = ?");
    pstmt.setString(1, "28959");
    ResultSet rs = pstmt.executeQuery();
    while (rs.next())
    {
        displayName(rs.getString(1));
         if (rs.isClosed() // The ResultSet is already closed while closing the connection!
         {
             throw new Exception("Your ResultSet has been prematurely closed! 
Your Statement object is also dead now.");
         }
    }
}

この例では、displayNameメソッドでプロキシ接続をクローズすると、PreparedStatementオブジェクトとResultSetオブジェクトもクローズされます。したがって、ループ内でResultSetオブジェクトのステータスをチェックしないと、そのループはnextメソッドが2度目にコールされたときに失敗します。

例2

    ....
    PreparedStatement pstmt = conn.prepareStatement("SELECT empname FROM EMP WHERE empno = ?");
    pstmt.setString(1, "28959");
    ResultSet rs = pstmt.executeQuery();
    while (rs.next())
    {
        ....
    }
 
    Properties props = new Properties();
    props.put("PROXY_USER_NAME", proxyUser);
 
    conn.openProxySession(OracleConnection.PROXYTYPE_USER_NAME, props);
    .......
    conn.close(OracleConnection.PROXY_SESSION);
 
    // Try to use the PreparedStatement again
    pstmt.setString(1, "28960");
// This line of code will fail because the Statement is already closed while closing the connection!
    rs = pstmt.executeQuery(); 

この例では、PreparedStatementオブジェクトとResultSetオブジェクトは、プロキシ接続をオープンする前はうまく機能します。しかし、同じPreparedStatementオブジェクトをプロキシ接続のクローズ後に実行しようとすると、その文は失敗します。