ORACLE JAPAN Server Release 6.1

 

  |  

  WebLogic Server ホーム   |     WebLogic Security   |   前へ   |   次へ   |   目次   |   索引   |   PDF 版

WebLogic Seurity SPI を使用したプログラミング

 

以下の節では、WebLogic Security SPI を使用したプログラミング方法について説明します。

 


始める前に

この章では、WebLogic Server で提供されている Security サービス プロバイダ インタフェース(SPI)のアプリケーション プログラミング インタフェース(API)によるプログラミングについて説明します。この章で説明するプログラミング タスクを実行する前に、以下のコンフィグレーション タスクが完了している必要があります。

  1. セキュリティ レルムの指定(デフォルトでは、代替セキュリティ レルムかカスタム セキュリティ レルム)

  2. セキュリティ レルムへのユーザとグループの追加

  3. セキュリティ レルム内のリソースへの ACL とパーミッションの割り当て

  4. SSL プロトコルのコンフィグレーション(省略可能。ネットワーク接続の保護を追加する場合、または証明書認証を使用する場合)

  5. 相互 SSL のコンフィグレーション(省略可能)

  6. 証明書認証のコンフィグレーション(省略可能)

以上のコンフィグレーション タスクの詳細については、『管理者ガイド』の「セキュリティの管理」を参照してください。

WebLogic EJB のセキュリティの詳細については、『WebLogic エンタープライズ JavaBeans プログラマーズ ガイド』を参照してください。

 


WebLogic Security SPI

WebLogic Security SPI は、Java Developer's Kit(JDK)のセキュリティ SPI を基にしています。必要に応じた実装と拡張、およびセキュリティ API を WebLogic Server の認証および認可サービスに収集するレルム インタフェースを提供します。WebLogic Server の認証方式は、Java Authentication and Authorization Service(JAAS)に基づいています。JAAS では、WebLogic Server へのセキュリティ保護された接続を行う際に、ユーザ名と資格(パスワードかデジタル証明書)を提出するのに必要なサポートが提供されます。

表 4-1 は、WebLogic Server 環境でのセキュリティに使用されるパッケージを示しています。

表4-1 WebLogic Security パッケージ

パッケージ名

使用目的

javax.security.auth

JAAS スタイルの LoginContext と主体ベースの認証を実行する場合。

weblogic.security

Web ブラウザと Java クライアントから送信されたデジタル証明書を WebLogic Server にマッピングする場合。このクラスを使用すると、有効なデジタル証明書を持っていれば、WebLogic Server のリソースにアクセスするときにユーザ名とパスワードを入力する必要がなくなる。

weblogic.security.acl

外部ストアから WebLogic Server のユーザ、グループ、または ACL にアクセスするためのカスタム セキュリティ レルムを作成する場合。このパッケージは、サーバサイド プログラムのカスタム ACL のテストにも使用する。

weblogic.security.audit

セキュリティ イベントを監査する場合。WebLogic Server は、認証および認可リクエストに関する情報を基に Audit クラスを呼び出す。このパッケージは、認証および認可リクエストをフィルタ処理してログ ファイルなどの管理機能に送信するのに使用できる。

weblogic.security.net

ネットワーク接続を開始したクライアントの IP アドレス、ドメイン、プロトコルなどの属性を基に接続を許可または拒否するために、WebLogic Server への接続を調べる場合。

weblogic.net.http.
HTTPsURLConnection

別の WebLogic Server に対するクライアントとして機能している WebLogic Server から発信 SSL 接続を確立する場合。

weblogic.security.SSL.HostNameVerifier

クライアント認証をサポートする。ホスト名検証クラス、トラスト マネージャ クラス、および SSL コンテキスト クラスが含まれる。


 

 


JAAS 認証の使い方

JAAS は、Java Development Kit バージョン 1.3 のセキュリティに対する標準拡張です。JAAS では、コードを実行するものに基づいてアクセス制御を実行できます。JAAS は、JNDI 認証メカニズムの代わりとして WebLogic Server で提供されています。WebLogic Server の認証方法としては、この JAAS が最も望ましいものです。JAAS を使用するには、Java SDK バージョン 1.3 をインストールする必要があります。

注意: JAAS の認可コンポーネントは WebLogic Server では提供されていません。

表 4-2 は、WebLogic Server でサポートされている JAAS クラスを示しています。

表4-2 JAAS クラス

クラス

説明

javax.security.auth.Subject

リクエストの送信元を表す。どのエンティティ(個人またはクライアントなど)でも構わない。Subject オブジェクトは、ユーザ認証またはログインが完了すると作成される。

javax.security.auth.login.LoginContext

LoginContext オブジェクトを介して、アプリケーションはログインとログアウトを行い、認可チェックのために、認証された主体を取得する。

javax.security.auth.login.Configuration

WebLogic Server の特定の実装で提供される LoginModule のリストを取得するための getConfiguration() メソッドを提供する。

javax.security.auth.spi.LoginModule

異なる種類の認証技術を WebLogic Server に実装できるようにする。たとえば、ある LoginModule オブジェクトではパスワードによる認証、別の LoginModule オブジェクトでは証明書による認証が可能になる。

javax.security.auth.callback.Callback

パスワードやデジタル証明書ファイルの名前など、ユーザからの入力をまとめて Java クライアントに渡す。

javax.security.auth.callback.Callback.
CallbackHandler

LoginModule から主体に通信して認証情報を取得できるようにする。CallbackHandler インタフェースを実装して LoginContext に渡す。LoginContext は、基本となる LoginModule に直接それを転送する。LoginModule では、ユーザ入力(パスワードなど)の収集とユーザへの情報(ステータス情報など)提供の両方を CallbackHandler で行う。CallbackHandler を使用すると、各 LoginModule は、他の通信方法から独立した形で WebLogic Server とユーザとの通信を制御できる。


 

Java クライアントで JAAS を使用して主体を認証するには、以下の手順を実行します。

  1. WebLogic Server で使用する認証メカニズム用に LoginModule クラスを実装します。認証メカニズムのタイプごとに LoginModule クラスが必要です。1 つの WebLogic Server デプロイメントに対して複数の LoginModule クラスを割り当てることができます。

    WebLogic Server では、LoginModule クラスの記述を簡便化することを目的にしたヘルパー クラス weblogic.security.auth.Authenticate が提供されています。weblogic.security.auth.Authenticate クラスでは、JNDI Environment オブジェクトを使用して認証された主体を返します。JNDI Environment オブジェクトには、 表 4-3 で示されているプロパティが指定されている必要があります。

  2. WebLogic Server でどの LoginModule クラスを使用し、どの順番で LoginModule クラスを呼び出すかを指定するために、Configuration クラスを実装します。

  3. Java クライアントで、LoginContext をインスタンス化します。

    LoginContext は、Configuration にアクセスして、WebLogic Server 用にコンフィグレーションされた LoginModule をすべてロードします。

  4. LoginContext の login() メソッドを呼び出します。

    login() メソッドによって、ロードされた LoginModule がすべて呼び出されます。各 LoginModule で主体の認証が試みられます。

    コンフィグレーションされたログイン条件に一致しなかった場合、LoginContext では LoginException が送出されます。

  5. LoginContext から認証された主体を取得します。

  6. 主体の認証に成功すると、javax.security.auth.Subject クラスの doAs() メソッドを呼び出せば、アクセス制御をその主体に設定できます。doAs() メソッドによって、指定した主体が現在のスレッドの ACL に関連付けられ、アクションが実行されます。主体に必要なアクセス制御がある場合、アクションは完了しますが、主体にそのアクセス制御がない場合、セキュリティ例外が送出されます。

samples\examples\security ディレクトリにある、WebLogic Server 付属の examples.security.jaas サンプルでは、Java クライアントの JAAS 認証の方法が示されています。

コード リスト 4-1 は、パスワード認証を実行する javax.security.auth.spi.LoginModule クラスの実装を示しています。 コード リスト 4-1 内のコードは、examples.security.jaas パッケージの SampleLoginModule からの抜粋です。

コード リスト 4-1 パスワード認証用の LoginModule の例

...

// 適切なクラスをインポートする //
import java.util.Map;
import java.io.IOException;
import java.net.MalformedURLException;
import java.rmi.RemoteException;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.spi.LoginModule;
import weblogic.security.auth.Authenticate;
import weblogic.jndi.Environment;

public class SampleLoginModule implements LoginModule
{
private Subject subject = null;
private CallbackHandler callbackHandler = null;
private Map sharedState = null;
private Map options = null;
private String url = null;

// 認証ステータス
private boolean succeeded = false;
private boolean commitSucceeded = false;

// ユーザ名とパスワード
private String username = null;
private String password = null;

// 初期化

public void initialize(Subject subject,
CallbackHandler callbackHandler,
Map sharedState,
Map options)

{

this.subject = subject;
this.callbackHandler = callbackHandler;
this.sharedState = sharedState;
this.options = options;

// WebLogic Server URL 文字列を取得

url = System.getProperty
("weblogic.security.jaas.ServerURL");

// 渡されたユーザ名とパスワードを使用するユーザを認証
// 成功の場合は true を返す
// 認証に失敗した場合は FailedLoginException を送出
// LoginModule が認証を実行できなかった場合は、LoginException を
// 送出

public boolean login() throws LoginException
{
// クライアントによってコールバック ハンドラが提供されたことを確認
if(callbackHandler == null)
throw new LoginException("No CallbackHandler Specified");

// コールバック リストを指定 //
Callback[] callbacks = new Callback[2];
callbacks[0] = new NameCallback("username: ");
callbacks[1] = new PasswordCallback("password: ", false);

// ユーザ名とパスワードの入力を要求
callbackHandler.handle(callbacks);

// ユーザ名を取得
username = ((NameCallback) callbacks[0]).getName();

// パスワードを取得し、char[] を String に変換
char[] charPassword = ((PasswordCallback)
callbacks[1]).getPassword();

if(charPassword == null)
{

// NULL パスワードを NULL ではなく空のパスワードとして扱う
charPassword = new char[0];
}
password = new String(charPassword);
}

// WebLogic 環境と認証を指定
Environment env = new Environment();
env.setProviderUrl(url);
env.setSecurityPrincipal(username);
env.setSecurityCredentials(password);

// ユーザの資格を認証し、主体を指定
Authenticate.authenticate(env, subject);

// 指定した情報で主体の認証に成功
succeeded = true;
return succeeded;

...

WebLogic Server では、デフォルトの LoginModule(weblogic.security.internal.ServerLoginModule)を使用して、サーバの初期化時に認証情報を収集します。デフォルトの Login モジュールを変更するには、Server.policy ファイルを編集し、デフォルト Login モジュール名をカスタム Login モジュール名に置き換えます。

WebLogic Server の JAAS 実装では、NameCallback、PasswordCallback、および TextInputCallback の各コールバックを、提供された LoginModule で使用できます。

server.policy ファイルで、カスタム Login モジュール名をデフォルト LoginModule の前に記述して指定することもできます。WebLogic Server の JAAS 実装では、server.policy ファイルで定義されている順番に従って Login モジュールが使用されます。デフォルト Login モジュールでは、実行の前に既存のシステム ユーザ認証が定義されているかどうかがチェックされ、既に定義されている場合は何の処理も行われません。

デフォルト Login モジュールでは、システム ユーザ名とパスワードの両方に対して JVM プロパティを定義する必要があります。それぞれ、weblogic.management.usernameweblogic.management.password で指定します。カスタム Login モジュールを使用するには、各モジュールの仕様に従ってこのプロパティを設定します。

コード リスト 4-2 は、javax.security.auth.login.Configuration クラスの実装を示しています。 コード リスト 4-2 内のコードは、examples.security.jaas パッケージの SampleConfig からの抜粋です。

コード リスト 4-2 コンフィグレーション実装の例

...
import java.util.Hashtable;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.AppConfigurationEntry;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class SampleConfig extends Configuration

{
String configFileName = null;

// Configuration オブジェクトを作成する
public SampleConfig()

// アプリケーション名をインデックスとして Configuration からエントリを
// 取得する。このコードでは、単独の LoginModule を指定した

public AppConfigurationEntry[]
getAppConfigurationEntry(String applicationName)
{

AppConfigurationEntry[] list =
new AppConfigurationEntry[1];
AppConfigurationEntry entry = null;

// 指定したコンフィグレーション ファイルを取得
configFileName =
System.getProperty("weblogic.security.jaas.Policy");
System.out.println("Using Configuration File: " +
configFileName);

try
{
FileReader fr = new FileReader(configFileName);
BufferedReader reader = new BufferedReader(fr);
String line;

line = reader.readLine();
while(line != null)
{

// 「{」で始まる行まで行をスキップ
if(line.length() == 0 || line.charAt(0) != '{')
{
line = reader.readLine();
continue;
}
// コンフィグレーションした LoginModule を含む次の行を読み取る
line = reader.readLine();

int i;
for(i = 0; i < line.length(); i++)
{
char c = line.charAt(i);
if(c != ' ')
break;
}
int sep = line.indexOf(' ', i);

String LMName = line.substring(0, sep).trim();
String LMFlag = line.substring(sep + 1)line.indexOf
(' ', sep + 1));

System.out.println("Login Module Name: " + LMName);
System.out.println("Login Module Flag: " + LMFlag);

if(LMFlag.equalsIgnoreCase("OPTIONAL"))
{
entry = new AppConfigurationEntry(LMName,
AppConfigurationEntry.LoginModuleControlFlag.
OPTIONAL,new Hashtable());
list[0] = entry;
}


else if(LMFlag.equalsIgnoreCase("REQUIRED"))
{
entry = new AppConfigurationEntry(LMName,
AppConfigurationEntry.LoginModuleControlFlag.
REQUIRED, new Hashtable());
list[0] = entry;
}


else if(LMFlag.equalsIgnoreCase("REQUISITE"))
{
entry = new AppConfigurationEntry(LMName,
AppConfigurationEntry.LoginModuleControlFlag.
REQUISITE, new Hashtable());
list[0] = entry;
}

else if(LMFlag.equalsIgnoreCase("SUFFICIENT"))

{
entry = new AppConfigurationEntry(LMName,
AppConfigurationEntry.LoginModuleControlFlag.
SUFFICIENT,new Hashtable());
list[0] = entry;

...
// 全 Login コンフィグレーションを更新および再ロード
public void refresh()

...

コード リスト 4-3 は、JAAS 認証を使用する Java クライアントの例を示しています。 コード リスト 4-3 内のコードは、examples.security.jaas パッケージの SampleClient からの抜粋です。Java クライアントには、javax.security.auth.callback.Callback.CallbackHandler クラスの実装があります。

コード リスト 4-3 JAAS 認証を使用する Java クライアントの例

// 必要なクラスをインポートする
import java.io.*;
import java.util.*;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.TextOutputCallback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.AccountExpiredException;
import javax.security.auth.login.CredentialExpiredException;

public class SampleClient
{

// ユーザ認証を試行
LoginContext loginContext = null;

// JAAS サーバ URL システム プロパティを設定し、LoginContext を作成
{

// SampleLoginModule のサーバ URL を設定、JAAS のコード例の
// LoginModule
Properties property = new
Properties(System.getProperties());
property.put("weblogic.security.jaas.ServerURL", args[0]);
System.setProperties(property);

// コンフィグレーション クラス名を設定して、SampleConfiguration をロード
// JAAS コード例の Configuration
property = new Properties(System.getProperties());
property.put("weblogic.security.jaas.Configuration",
"examples.security.jaas.SampleConfig");
System.setProperties(property);

// Configuration ファイル名を設定してサンプル コンフィグレーション ポリ
// シー ファイルをロード
property = new Properties(System.getProperties());
property.put("weblogic.security.jaas.Policy",
"Sample.policy");
System.setProperties(property);

// LoginContext を作成
loginContext = new LoginContext("SampleLoginModule", new
MyCallbackHandler());
}

// 認証を試行
loginContext.login();

// 認証された主体を取得し、SampleAction を主体として実行
Subject subject = loginContext.getSubject();
SampleAction sampleAction = new SampleAction();
Subject.doAs(subject, sampleAction);

// CallbackHandler インタフェースの実装
class MyCallbackHandler implements CallbackHandler

{
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
{
for(int i = 0; i < callbacks.length; i++)
{
if(callbacks[i] instanceof TextOutputCallback)
{
// 指定したタイプに従ってメッセージを表示
TextOutputCallback toc = (TextOutputCallback) callbacks[i];
switch(toc.getMessageType())
{
case TextOutputCallback.INFORMATION:
System.out.println(toc.getMessage());
break;
case TextOutputCallback.ERROR:
System.out.println("ERROR: " + toc.getMessage());
break;
case TextOutputCallback.WARNING:
System.out.println("WARNING: " + toc.getMessage());
break;
default:
throw new IOException("Unsupported message type: " +
toc.getMessageType());
}
}
else if(callbacks[i] instanceof NameCallback)

{
// ユーザ名の入力を要求
NameCallback nc = (NameCallback) callbacks[i];
System.err.print(nc.getPrompt());
System.err.flush();
nc.setName((new BufferedReader(new
InputStreamReader(System.in))).readLine());
}else if(callbacks[i] instanceof PasswordCallback)

{
// パスワードの入力を要求
PasswordCallback pc = (PasswordCallback) callbacks[i];
System.err.print(pc.getPrompt());
System.err.flush();

// JAAS は、パスワードが String ではなく char[] であるように指定
String tmpPassword = (new BufferedReader(new
InputStreamReader(System.in))).readLine();

int passLen = tmpPassword.length();
char[] password = new char[passLen];
for(int passIdx = 0; passIdx < passLen; passIdx++)
password[passIdx] = tmpPassword.charAt(passIdx);
pc.setPassword(password);
}
else
{
throw new UnsupportedCallbackException(callbacks[i],
"Unrecognized Callback");
}
...

JAAS 使用の詳細については、『 Java Authentication and Authorization Service Developer's Guide』を参照してください。

 


JNDI 認証の使い方

Java クライアントでは JNDI を使用して資格を渡すこともできます。Java クライアントは、JNDI InitialContext を取得して WebLogic Server との通信を確立しますその後、InitialContext を使用して、WebLogic Server JNDI ツリーで必要なリソースをルックアップします。

ユーザとユーザの資格を指定するには、次の表で示されている JNDI プロパティを設定します。

表4-3 認証に使用される JNDI プロパティ

プロパティ

意味

INITIAL_CONTEXT_FACTORY

エントリ ポイントを WebLogic Server 環境に提供する。weblogic.jndi.WLInitialContextFactory クラスは WebLogic Server 用の JNDI SPI。

PROVIDER_URL

WebLogic Server のホストとポートを指定する。例 : t3://weblogic:7001

SECURITY_AUTHENTICATION

使用する認証のタイプを示す。以下の値を使用できる。

  • None の場合、認証は実行されない。

  • Simple の場合、パスワードによる認証が実行される。

  • Strong の場合、証明書による認証が実行される。

注意: WebLogic Server 上のセキュア コンポーネントへのアクセスを試みる場合、SECURITY_AUTHENTICATION の設定によって指定される認証のタイプに関係なく、WebLogic Server でユーザ認証が必須となる。たとえば、SECURITY_AUTHENTICATIONNone に設定すると、セキュア コンポーネントにアクセスする場合にも正しいパスワードの指定が必要になる。

SECURITY_PRINCIPAL

ユーザが WebLogic Server セキュリティ レルムに対して認証されているときのユーザの ID を指定する。

SECURITY_CREDENTIALS

ユーザが WebLogic Server セキュリティ レルムに対して認証されているときのユーザの資格を指定する。

  • SECURITY_AUTHENTICATION="simple" で有効化するパスワード認証の場合、このプロパティは、ユーザのパスワードを表す文字列か、または資格の検証に使用される User オブジェクトを表す文字列を指定する。

  • SECURITY_AUTHENTICATION="strong" で有効化する証明書認証の場合、このプロパティは、WebLogic Server のデジタル証明書とプライベート キーを格納する X509 オブジェクトの名前を指定する。

 

これらのプロパティは、InitialContext コンストラクタに渡されるハッシュ テーブルに格納されます。

コード リスト 4-4 は、Java クライアントでパスワード認証を使用する方法を示しています。 コード リスト 4-4 のコードは、samples\examples\security ディレクトリにある、WebLogic Server 付属の examples.security.acl サンプルの Client からの抜粋です。

コード リスト 4-4 パスワード認証の例

...
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
env.put(WLContext.PROVIDER_URL, "t3://weblogic:7001");
env.put(WLContext.SECURITY_AUTHENTICATION "simple");
env.put(Context.SECURITY_PRINCIPAL, "javaclient");
env.put(Context.SECURITY_CREDENTIALS, "password");

ctx = new InitialContext(env);

コード リスト 4-5 は、Java クライアントで証明書認証を使用する方法を示しています。SSL プロトコルを介した WebLogic Server 独自のプロトコルである T3S プロトコルの使用に注意してください。SSL プロトコルは、WebLogic Server と Java クライアントの間の接続および通信を保護します。

コード リスト 4-5 証明書認証の例

...
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
env.put(WLContext.PROVIDER_URL, "t3s://weblogic:7001");
env.put(WLContext.SECURITY_AUTHENTICATION "strong");
env.put(Context.SECURITY_PRINCIPAL, "javaclient");
env.put(Context.SECURITY_CREDENTIALS, "certforclient");

ctx = new InitialContext(env);

コード リスト 4-4 コード リスト 4-5 のコードでは、ユーザ名とパスワードが正しい場合や、デジタル証明書が有効な場合に User オブジェクトを返す、weblogic.security.acl.Security.getUser() の呼び出しが生成されます。WebLogic Server では、この認証された User オブジェクトは WebLogic Server 内の Java クライアントのスレッドに格納されます。格納された User オブジェクトは、以降の認可リクエストで、スレッドが ACL で保護されているリソースにアクセスする際に使用されます。

注意: JNDI コンテキストとスレッドについて、および JNDI コンテキストで発生する可能性のある問題を避ける方法については、『WebLogic JNDI プログラマーズ ガイド』の「JNDI コンテキストとスレッド」および「JNDI コンテキストの潜在的な問題を避ける方法」を参照してください。

 


SSL 対応 Web ブラウザとの安全な通信

URL オブジェクトを使用すると、別の WebLogic Server に対するクライアントとして機能している WebLogic Server から発信 SSL 接続を確立することができます。weblogic.net.http.HttpsURLConnection クラスを使用して、プライベート キーとデジタル証明書を含む、クライアントのセキュリティ コンテキスト情報を指定できます。

weblogic.net.http.HttpsURLConnection クラスは、ネゴシエーションされた暗号スイートの判別、ホスト名検証の取得と設定、サーバの認証チェーンの取得、および新しい SSL ソケットを作成するための SSLSocketFactory の取得と設定を行うメソッドを提供します。

SSL クライアントのコード例には、weblogic.net.http.HttpsURLConnection クラスを使用して発信 SSL 接続を確立する方法が示されています。さらに、SSL クライアントのコード例には、Java Secure Socket Extension(JSSE)アプリケーション プログラミング インタフェース(API)を使用して、発信 SSL 接続を確立する方法も示されています。SSL クライアントのコード例は、\samples\examples\security\sslclient ディレクトリの examples.security.sslclient パッケージにあります。

 


相互認証の使い方

証明書認証では、WebLogic Server は、リクエストを発したクライアントにデジタル証明書を送信します。クライアントは、デジタル証明書を調べて、本物かどうか、期限切れでないかどうか、認証元の WebLogic Server に一致しているかどうかを確認します。

相互認証では、リクエストを発したクライアントの側も WebLogic Server にデジタル証明書を送信します。Administration Console の各フィールドを設定して WebLogic Server のコンフィグレーションを変更すると、指定した認証局からデジタル証明書を送信するようにリクエスト元のクライアントに要求できるようになります。WebLogic Server では、指定した認証局のルート証明書によって署名されたデジタル証明書のみが受け付けられます。詳細については、「セキュリティの管理」の「SSL プロトコルのコンフィグレーション」を参照してください。

以降の節では、相互認証を WebLogic Server に実装するさまざまな方法について説明します。

注意: Java クライアントの認証で JAAS を使用する場合、相互認証を実行する LoginModule クラスを記述します。

JNDI による相互認証

Java クライアントの認証で JNDI を使用する場合、WebLogic JNDI Environment クラスの setSSLClientCertificate() メソッドを使用します。このメソッドは、クライアント認証に対して、X.509 デジタル証明書のプライベート キーと認証チェーンを設定します。Java クライアントのデジタル証明書とプライベート キーを提供するには、デジタル証明書とプライベート キーを含む Definite Encoding Rules(DER)ファイルを X509 オブジェクトに読み込んで、JNDI ハッシュ テーブルにその X509 オブジェクトを設定します。 JNDI 認証の使い方で説明されている JNDI プロパティを使用して、認証に必要な情報を指定します。

デジタル証明書を JNDI に渡すには、DER エンコードされたデジタル証明書を格納するファイルで開かれている InputStreams の配列を作成し、JNDI ハッシュ テーブルにその配列を設定します。配列内の最初の要素には、Java クライアントのプライベート キー ファイルで開かれている InputStream が格納されている必要があります。配列内の 2 番目の要素には、Java クライアントのデジタル証明書ファイルで開かれている InputStream が格納されている必要があります(このファイルには Java クライアントの公開鍵が含まれています)。追加要素として、ルート認証局のデジタル証明書、認証チェーン内のデジタル証明書の署名者を格納できます。デジタル証明書が fileRealm.properties ファイルの Java クライアントで登録された認証局によって直接発行されない場合、WebLogic Server は、認証チェーンを使用して Java クライアントのそのデジタル証明書を認証できます。

weblogic.security.PEMInputStream クラスを使用すると、Privacy Enhanced Mail(PEM)ファイルに保存されているデジタル証明書を読み込むことができます。このクラスでは、ベース 64 でエンコードされた DER 認証を PEM ファイルにデコードするフィルタが提供されます。

コード リスト 4-6 は、Java クライアントで相互認証を使用する方法を示しています。 コード リスト 4-6 のコードは、samples\examples\security ディレクトリにある、WebLogic Server 付属の examples.security.acl サンプルの AltClient からの抜粋です。

コード リスト 4-6 相互認証の例

package examples.security.acl;

import java.io.FileInputStream;
import java.io.InputStream;
import javax.naming.Context;
import weblogic.jndi.Environment;
import weblogic.security.PEMInputStream;


public class AltClient
{

public static void main(String[] args)
{
Context ctx = null;

String url = args[0];
try
{
Environment env = new Environment();

env.setProviderUrl(url);

// 2 番目と 3 番目の引数はユーザ名とパスワード
if (args.length >= 3)
{
env.setSecurityPrincipal(args[1]);
env.setSecurityCredentials(args[2]);
}

// 4 番目と 5 番目の引数はプライベート キーと
// 公開鍵
if (url.startsWith("t3s") && args.length >= 5)
{
InputStream[] certs = new InputStream[args.length - 3];
for (int q = 3; q < args.length; q++)
{
String file = args[q];
InputStream is = new FileInputStream(file);

if (file.toLowerCase().endsWith(".pem"))
{
is = new PEMInputStream(is);
}
certs[q - 3] = is;
}
env.setSSLClientCertificate(certs);
}
ctx = env.getInitialContext();
...

JNDI の getInitialContext() メソッドが呼び出されると、Java クライアントと WebLogic Server は、Web ブラウザが相互認証を実行してセキュリティ保護された Web サーバ接続を取得するのと同じ方法で相互認証を実行します。デジタル証明書を確認できない場合や Java クライアントのデジタル証明書をセキュリティ レルムで認証できない場合、例外が送出されます。認証された User オブジェクトは Java クライアントのサーバ スレッドに格納され、ACL 保護された WebLogic Server リソースへの Java クライアントのアクセスを管理するパーミッションのチェックに使用されます。

WebLogic JNDI Environment クラスを使用する場合、getInitialContext() メソッドの呼び出しごとに Environment オブジェクトを作成する必要があります。ユーザとセキュリティ資格を一度指定すると、ユーザおよびユーザに関連する資格は Environment オブジェクトの設定に残ります。再設定を試みて JNDI getInitialContext() メソッドを呼び出した場合は、元のユーザと資格が使用されます。

Java クライアントによる相互認証を使用する場合、WebLogic Server は、クライアント JVM ごとにユニークな Java 仮想マシン(JVM) ID を取得し、Java クライアントと WebLogic Server の間の接続が切断されないようにします。処理がないために接続がタイムアウトになるまで、Java クライアントの JVM が実行されている間は接続が続行されます。Java クライアントが新しい SSL 接続を確実にネゴシエーションできる唯一の方法は、その JVM を停止して JVM の他のインスタンスを実行することです。

SSL 接続の JVM で動作している Java クライアントは、新しい JNDI InitialContext を作成し、JNDI SECURITY_PRINCIPALSECURITY_CREDENTIALS プロパティで新しいユーザ名とパスワードを指定して WebLogic Server ユーザの ID を変更できます。SSL 接続後に Java クライアントによって渡されたデジタル証明書は使用されません。新しい WebLogic Server ユーザは、最初のユーザのデジタル証明書でネゴシエーションした SSL 接続を使用し続けます。

CertAuthenticator インタフェースを実装している場合、WebLogic Server は、Java クライアントに対するデジタル証明書を CertAuthenticator クラスの実装に渡します。CertAuthenticator クラスは、デジタル証明書を WebLogic Server ユーザにマッピングします。デジタル証明書は、JVM からの最初の接続リクエスト時にのみ処理されるため、CertAuthenticator クラスを使用するときに新しいユーザ ID 設定することはできません。

注意: JNDI コンテキストとスレッドについて、および JNDI コンテキストで発生する可能性のある問題を避ける方法については、『WebLogic JNDI プログラマーズ ガイド』の「JNDI コンテキストとスレッド」および「JNDI コンテキストの潜在的な問題を避ける方法」を参照してください。

WebLogic Server ユーザへのデジタル証明書のマッピング

相互認証を実行すると、WebLogic Server は、SSL 接続を確立するために Web ブラウザまたは Java クライアントのデジタル証明書を認証します。ただし、デジタル証明書は Web ブラウザまたは Java クライアントを WebLogic Server セキュリティ レルムのユーザとしては認識しません。Web ブラウザまたは Java クライアントが ACL で保護された WebLogic Server リソースをリクエストすると、WebLogic Server は Web ブラウザまたは Java クライアントにユーザ名とパスワードを指定するように要求します。

Web ブラウザまたは Java クライアントを WebLogic Server セキュリティ レルム内のユーザにマップするには、weblogic.security.acl.CertAuthenticatorインタフェースを実装します。SSL 接続が確立されると、CertAuthenticator クラスが呼び出されます。このクラスは、デジタル証明書からデータを抽出し、どのユーザがデジタル証明書のオーナかを決定します。次に、CertAuthenticator クラスは weblogic.security.acl.getUser() メソッドを呼び出して認証された User オブジェクトを WebLogic Server セキュリティ レルムから取得します。

CertAuthenticator クラスがインストールされると、Web ブラウザで WebLogic Server ユーザ名の入力を要求する必要はなくなります。また、Java アプリケーションの JNDI SECURITY_CREDENTIALS プロパティでパスワードを設定する必要もなくなります。詳細については、「セキュリティの管理」の「SSL プロトコルのコンフィグレーション」を参照してください。

Java クライアント アプリケーションで CertAuthenticator クラスを使用する場合、SSL 接続が確立されると Java クライアントはユーザ ID を変更できません。新しいデジタル証明書を提供するには、Java クライアントの JVM を停止して、新しい JVM インスタンスでクライアントを再起動し、SSL 接続をネゴシエーションできるようにします。

いくつかあるメソッドのいずれかを使用すると、デジタル証明書をユーザにマップできます。たとえば、ユーザのパスワードをユーザのデジタル証明書のフィンガープリントに設定するという方法があります。次に、デジタル証明書からユーザ名を抽出し、フィンガープリントを計算し、ユーザがユーザ名とパスワードを提出してリソースにアクセスするときに WebLogic Server が行うのと同じ方法で weblogic.security.acl.getUser() メソッドを呼び出すことができます。

注意: デジタル証明書のフィンガープリントは証明書の一部ではありませんが、証明書から計算できます。フィンガープリントは、DER でエンコードした CertificateInfo の MD5 ダイジェストです。これは、X.509 仕様に含まれている ANS.1 タイプです。

CertAuthenticator クラスは、引数なしのパブリック コンストラクタを持っており、authenticate() メソッドを呼び出します。WebLogic Server は、ユーザ名(空のままでも構いません)、Java クライアントまたは認証チェーンのデジタル証明書を格納した Certificate 配列、SSL ハンドシェークが成功した場合に true となるブール値を指定した authenticate() メソッドを呼び出します。Certificate 配列でメソッドを呼び出してデジタル証明書からデータを取得できます。

コード リスト 4-7 は、CertAuthenticator インタフェースの実装方法を示しています。このインタフェースでは、デジタル証明書の電子メール アドレスからユーザ名を抽出し、weblogic.security.acl.getUser() メソッドを呼び出して WebLogic Server セキュリティ レルムから認証された User オブジェクトを取得します。コード例では、電子メール アドレスの一部のみを調べています。そのため、セキュリティについては万全ではありません。異なるドメインで同じ電子メール アドレスを持つ複数のデジタル証明書は、同じユーザにマップされ、追加認証が実行されない場合があります。この機能を実装する場合、クライアントの ID を完全に確立するコードを追加することもできます。

コード リスト 4-7 は、WebLogic Server セキュリティ レルムのユーザにデジタル証明書をマップする方法も示しています。 コード リスト 4-7 のコードは、samples\examples\security ディレクトリにある、WebLogic Server 付属の examples.security.cert サンプルの SimpleCertAuthenticator からの抜粋です。

コード リスト 4-7 WebLogic Server ユーザへのデジタル証明書のマッピングの例


package examples.security.cert;


import weblogic.security.Certificate;
import weblogic.security.Entity;
import weblogic.security.X500Name;
import weblogic.security.acl.CertAuthenticator;
import weblogic.security.acl.BasicRealm;
import weblogic.security.acl.Realm;
import weblogic.security.acl.User;

public class SimpleCertAuthenticator
implements CertAuthenticator
{
private BasicRealm realm;

public SimpleCertAuthenticator()
{
realm = Realm.getRealm("weblogic");
}


/**
* リモート ユーザの認証を試行
*  
* @ この例では、param userName は無視
* @ param certs を使用して 電子メール アドレスから
* @ WebLogic ユーザへのマップを試行
* @ param ssl が false の場合、この例では null を返す
* @ 認証されたユーザまたは null(認証失敗の場合)を返す
*/
public User authenticate(String userName, Certificate[] certs, boolean ssl)
{
// この実装では、成功した相互 SSL ハンドシェークによる
// 証明書のみを信頼する
if (ssl == false)
{
return null;
}

User result = null;
Certificate cert = certs[0];
Entity holder = cert.getHolder();

if (holder instanceof X500Name)
{
X500Name x500holder = (X500Name) holder;
String email = x500holder.getEmail();

if (email != null)
{
int at = email.indexOf("@");

if (at > 0)
{
String name = email.substring(0, at);

// 電子メール アドレスから抽出したユーザが
// 実際に存在することを確認
result = realm.getUser(name);
}
}
}

return result;
}
}

コード リスト 4-7 のコンストラクタでは、サーバサイド クラスで WebLogic Server セキュリティ レルムにアクセスする方法が示されています。weblogic.security.acl.realm クラスの getRealm("weblogic") メソッドは、ファイル レルムか代替セキュリティ レルム(LDAP セキュリティ レルムなど)に関係なく、WebLogic Server で使用されるレルムを返します。

weblogic.security.X500Name クラスには、weblogic.security.Certificate クラスからフィールドを取得するためのアクセサ メソッドが含まれています。 コード リスト 4-7 では、Certificate オブジェクトを X500Name オブジェクトにキャストし、X500Name オブジェクトの getEmail() メソッドを呼び出して、電子メール アドレスの最初の部分文字列を取得しています。weblogic.security.acl.AbstractableRealm クラスの getUser(String) メソッドは、指定したユーザ名の WebLogic Server ユーザを取得します。ユーザが存在しない場合は、weblogic.security.acl.AbstractableRealm クラスの authenticate() メソッドは null を返します。

他の WebLogic Server との相互認証の使い方

一方の WebLogic Server がもう一方の WebLogic Server のクライアントとして機能するサーバ間通信で相互認証を使用できます。サーバ間通信で相互認証を使用すると、一般的なクライアント/サーバ環境でない場合でも、高度なセキュリティの接続に依存することができます。

コード リスト 4-8 は、WebLogic Server で動作しているサーブレットから server2.weblogic.com という 2 番目の WebLogic Server に対して、セキュリティ保護された接続を確立しています。

コード リスト 4-8 他の WebLogic Server へのセキュリティ保護された接続の確立

...

FileInputStream [] f = new FileInputStream[3];
f[0]= new FileInputStream("demokey.pem");
f[1]= new FileInputStream("democert.pem");
f[2]= new FileInputStream("ca.pem");

Environment e = new Environment ();
e.setProviderURL("t3s://server2.weblogic.com:443");
e.setSSLClientCertificate(f);
e.setSSLServerName("server2.weblogic.com");
e.setSSLRootCAFingerprints("ac45e2d1ce492252acc27ee5c345ef26");

T3Client t3c = e.createProviderClient();
t3c.connect();

e.setInitialContextFactory
("weblogic.jndi.WLInitialContextFactory");
Context ctx = new InitialContext(e.getProperties())

...

コード リスト 4-8 では、WebLogic JNDI Environment クラスは、以下のパラメータを格納するハッシュ テーブルを作成します。

注意: JNDI コンテキストとスレッドについて、および JNDI コンテキストで発生する可能性のある問題を避ける方法については、『WebLogic JNDI プログラマーズ ガイド』の「JNDI コンテキストとスレッド」および「JNDI コンテキストの潜在的な問題を避ける方法」を参照してください。

サーブレットによる相互認証の使い方

Java クライアントをサーブレット(または他のサーバサイド Java クラス)で認証するには、クライアントがデジタル証明書を提供したかどうかをチェックする必要があります。提供した場合は、証明書が信頼できる認証局で発行されたかどうかをさらにチェックします。サーブレットの作成者には、Java クライアントが有効なデジタル証明書を持っているかどうかを尋ねる役割があります。WebLogic Servlet API でサーブレットを作成する場合、HTTPServletRequest オブジェクトの getAttribute() メソッドで SSL 接続に関する情報にアクセスする必要があります。

以下の属性が、WebLogic Server サーブレットでサポートされています。

デジタル証明書に定義されているユーザ情報にアクセスできます。デジタル証明書には、以下のような情報が指定されています。

デジタル証明書を提供する X509 オブジェクトで to_string() メソッドを呼び出すと、各デジタル証明書の使用可能な情報を参照できます。

X509 オブジェクトをコンストラクタに渡すと、デジタル証明書に対する weblogic.security.JDK11Certificate オブジェクトを作成できます。weblogic.security.JDK11Certificate クラスは、java.security.Certificate インタフェースを実装します。

コード リスト 4-9 は、X509 オブジェクトの配列内の最初の X509 オブジェクトを JDK111Certificate オブジェクトに変換しています。

コード リスト 4-9 X509 オブジェクトの JDK111Certificate オブジェクトへの変換

weblogic.security.JDK11Certificate jdk11cert =
new weblogic.security.JDK111Certificate(X509certs [0]);

print(out, "jdk11cert.getPrincipal().getName() -",
jdk11cert.getPrincipal().getName() );
print(out, "jdk11cert.getGuarantor().getName() -",
jdk11cert.getGuarantor().getName() );

weblogic.security.JDK11Certificate クラスには、デジタル証明書に関する情報を提供する以下のメンバー関数があります。

 


カスタム ホスト名検証の使い方

ホスト名検証は、SSL 接続先のホストが予定していた通信先、または許可された通信先であることを確認します。WebLogic Server または WebLogic クライアントが別のアプリケーション サーバの SSL クライアントとして機能している場合には、介在者の攻撃を防ぐことができて便利です。

WebLogic Server の SSL ハンドシェーク機能としてのデフォルトの動作は、SSL サーバのデジタル証明書の SubjectDN にある共通名と、SSL 接続の開始に使用する SSL サーバのホスト名を比較することです。これらの名前が一致しない場合は SSL 接続が中断されます。

SSL接続の中断は、サーバのホスト名をデジタル証明書と照らし合わせて有効性を検証する SSL クライアントによって実行されます。デフォルト以外の動作が必要な場合は、ホスト名検証を無効にするか、カスタム ホスト名検証を登録します。ホスト名検証を無効にすると、WebLogic Server は介在者の攻撃に対して無防備な状態になります。

注意: ホスト名検証は、WebLogic Server に付属のデモ用デジタル証明書を使用しているときに無効にします。

ホスト名検証は、以下の方法で無効にできます。

カスタム ホスト名検証を記述できます。weblogic.security.SSL.HostnameVerifier インタフェースではコールバック メカニズムが提供されるため、接続先のサーバ名がサーバのデジタル証明書の SubjectDN にあるサーバ名と一致しない場合を処理するためのポリシーを定義できます。

カスタム ホスト名検証を使用するには、weblogic.security.SSl.HostnameVerifier インタフェースを実装するクラスを作成し、サーバのセキュリティ ID に関する情報を取得するメソッドを定義します。

カスタム ホスト名検証を使用する前に、以下の方法で実装するクラスを定義する必要があります。

デフォルトでない JDK プロトコル ハンドラを使用して接続を確立するには、以下の 2 つの関数を呼び出してハンドラを初期化する必要があります。

weblogic.net.http.Handler.init();
weblogic.management.application.Handler.init();

カスタム ホスト名検証の例については、\samples\examples\security\sslclient ディレクトリの examples.security.sslclient パッケージにある SSL クライアントのコード例を参照してください。このコード例には、比較のために常に true を返す NullHostnameVerifier クラスが含まれています。このサンプルでは、WebLogic SSL クライアントは、サーバのホスト名とデジタル証明書の SubjectDN との比較に関係なく、どの SSL サーバにも接続できます。

ホスト名検証のインスタンスは、 setHostnameVerifier メソッドを使用して SSL コンテキストに関連付けることができます。次に例を示します。

public void setHostnameVerifier (HostnameVerifier hv)

詳細については、「 SSL コンテキストの使用」を参照してください。

 


トラスト マネージャの使用

weblogic.security.SSL.TrustManager クラスを使用すると、ピアのデジタル証明書内での検証エラーをオーバーライドし、SSL ハンドシェークを継続できます。また、サーバのデジタル証明書チェーンで付加的な検証を実行することで、SSL ハンドシェークを中止することもできます。

SSL クライアントが SSL サーバに接続すると、SSL サーバは認証のためにデジタル証明書チェーンをクライアントに提示します。提示されたチェーンに無効なデジタル証明書が含まれている場合もあります。SSL 仕様では、クライアントが無効な証明書を検出した場合、SSL 接続が中断されることになっています。しかし、Web ブラウザは、証明書チェーン内の残りの証明書を使用して SSL サーバを認証できるかどうかを判別するため、無効な証明書を無視してチェーンの検証を継続します。トラスト マネージャを使用すると、どのような場合に SSL 接続を継続するか(または中止するか)を制御でき、上記のような矛盾した動作をなくすことができます。

トラスト マネージャを作成するには、weblogic.security.SSL.TrustManager クラスを使用します。このクラスには、証明書を検証するための一連のエラー コードが含まれています。また、必要に応じて、ピア証明書での付加的な検証を実行したり、SSL ハンドシェークを中断したりできます。デジタル証明書の検証が済むと、weblogic.security.SSL.TrustManager クラスがコールバック関数を使用してデジタル証明書の検証結果をオーバーライドします。トラスト マネージャのインスタンスは、setTrustManager() メソッドを使用して SSL コンテキストに関連付けることができます。weblogic.security.SSL.TrustManager クラスは、JSSE 仕様に準拠しています。トラスト マネージャを使用しても、パフォーマンスには影響ありません。トラスト マネージャはプログラムでのみ設定できます。その使用は、Administration Console やコマンドラインでは定義できません。

トラスト マネージャの使用例は、\samples\examples\security\sslclient ディレクトリに格納されています。

 


SSL コンテキストの使用

SSL コンテキストを使用すると、特定の SSL 接続のホスト名検証やトラスト マネージャなど、さまざまな情報を格納するセキュア ソケット プロトコルを実装できます。SSL コンテキスト クラスのインスタンスは、SSL ソケット用のファクトリとして使用します。たとえば、SSL コンテキストが提供するソケット ファクトリによって作成されたすべてのソケットは、SSL コンテキストに関連付けられたハンドシェーク プロトコルを使用することによってセッション ステートを一致させることができます。各インスタンスは、認証の実行に必要なキー、認証チェーン、および信頼されたルート CA を使用してコンフィグレーションできます。これらのセッションはキャッシュされます。このため、同じ SSL コンテキストで作成された他のソケットは、その後もセッションを再利用できます。セッションのキャッシュについての詳細は、『管理者ガイド』の「SSL セッション キャッシングのパラメータの変更」を参照してください。トラスト マネージャ クラスのインスタンスを SSL コンテキストに関連付けるには setTrustManager メソッドを使用します。

SSL コンテキストは、プログラムでのみ設定できます。Administration Console やコマンドラインでは設定できません。SSL コンテキスト オブジェクトは、Java の new 式または SSL コンテキスト クラスの getInstance() ファクトリ メソッドで作成できます。getInstance() ファクトリ メソッドは静的で、セキュア ソケット プロトコルを実装するためのインスタンスを返します。SSL コンテキストの使用例は、\samples\examples\security\sslclient ディレクトリに格納されています。

SSL コンテキストは、Sun Microsystems の Java Secure Socket Extension(JSEE)に準拠した上位互換コードです。

 


カスタム ACL の使い方

WebLogic Server では、リソースを保護するアクセス制御リスト(ACL)の標準セットが定義されます。リソースに対して ACL を作成すると、WebLogic Server では、ユーザがアクセスする前にそのリソースに対するパーミッションが自動的にチェックされます。WebLogic Server のほとんどのリソースは、この標準 ACL によって完全に保護されます。

ただし、一部のリソースでは、標準 ACL よりも詳細な保護が必要になります。WebLogic Server では、そのようなリソースに対するセキュリティを強化できます。たとえば、特定のデータを Web ページに書き込む前にユーザ パーミッションをチェックするサーブレットを作成することが可能です。weblogic.security.acl.Security クラスは、ACL のチェックなど、レルムの操作に対するアクセス権を提供します。このクラスはサーバサイド コードに対してのみ利用できます。

weblogic.security.acl.Security クラスの Security.hasPermission() メソッドと Security.checkPermission() メソッドは、リソースへのアクセスに必要なパーミッションをユーザが持っているかどうかをテストします。この 2 つのメソッドはよく似ていますが、Security.hasPermission() メソッドではブール値(ユーザがパーミッションを持っている場合は true)が返されるのに対して、Security.checkPermission() メソッドでは、ユーザがパーミッションを持っていない場合は java.lang.SecurityException が送出されるという違いがあります。

WebLogic Server 付属の examples.security.acl サンプル(samples\examples\security ディレクトリにある)では、独自の ACL を作成してサーバサイド クラスでテストする方法が示されています。この例では、frob というパーミッションを持つカスタム ACL aclexample で、RMI クラス FrobImpl が保護されます。

注意: カスタム ACL を使用する前に、WebLogic Server で使用するセキュリティ レルムに ACL を組み込む必要があります。

カスタム ACL を使用するには、Java クライアント アプリケーションは以下の作業を行う必要があります。

  1. JNDI InitialContext を WebLogic Server から取得します。

  2. パーミッション名で、WebLogic Server JNDI ツリー内の保護されているリソースをルックアップします。たとえば、Java クライアントはパーミッション名 frobFrobImpl をルックアップします。

  3. RMI スタブの frob() メソッドを実行します。

FrobImpl クラスには、ACL をテストするサーバサイド コードがあります。 コード リスト 4-10 に、weblogic.security.acl.realm クラスの静的メソッド checkPermission() でカスタム ACL をテストする方法を示します。

コード リスト 4-10 デフォルト セキュリティ レルムでのカスタム ACL のテスト

Security.checkPermission(Security.getCurrentUser(),
"aclexample",
Security.getRealm().getPermission("frob"),
'.');

カスタム ACL を代替セキュリティ レルムでテストすることもできます。

  1. weblogic.security.acl.realm クラスの getRealm(realm_name) メソッドで代替セキュリティ レルムを取得します。

  2. weblogic.security.acl.realm クラスの getACL() メソッドと getPermission() メソッドでカスタム ACL とパーミッションを取得します。

  3. acl.checkPermission() メソッドを呼び出してパーミッションをテストします。

コード リスト 4-11 は、この方法でカスタム ACL をテストしています。

コード リスト 4-11 代替セキュリティ レルムでのカスタム ACL のテスト

User p = Security.getCurrentUser();
BasicRealm realm = Realm.getRealm(realm_name);
Acl acl = realm.getAcl(acl_name);
Permission perm = realm.getPermission(permission_name);
boolean result = acl == null || !acl.checkPermission(p, perm);

コード リスト 4-11 の最後の行では、カスタム ACL があったかどうか、ユーザ pfrob パーミッションを持っているかどうかをテストしています。戻り値は通常の感覚と逆です。ACL が存在し、ユーザが frob パーミッションを持っている場合、結果は false になります。

セキュリティ レルムが getACL() 機能を実装していない場合、java.lang.UnsupportedOperationException 例外を送出します。 これで、ACL ルックアップはセカンダリ レルムに返ります。セカンダリ レルムがコンフィグレーションされていない場合には、ランライム エラーが発生します。

セキュリティ イベントを監査し、 コード リスト 4-12 の方法でパーミッションをテストする場合、パーミッション テストを監査するには、weblogic.security.audit パッケージの静的クラス Audit を明示的に呼び出す必要があります。Audit クラスを呼び出すと、WebLogic Server の AuditProvider クラスに対してパーミッション チェック イベントの通知が生成されます。

コード リスト 4-12 パーミッションのテスト

Audit.checkPermission("Frob", acl, p, perm, !result);

カスタム ACL を使用する完全なコード例については、samples\examples\security ディレクトリにある、WebLogic Server 付属の examples.security.acl パッケージを参照してください。

 


カスタム セキュリティ レルムの作成

ネットワーク上のディレクトリ サーバなどの環境にある既存のセキュリティ ストアを基に独自のセキュリティ レルムを作成できます。認証をサポートするカスタム セキュリティ レルムを作成するには、以下のコードを記述する必要があります。

  1. カスタム セキュリティ レルムの User クラスを定義するコード

  2. カスタム セキュリティ レルムの Group クラスを定義するコード

  3. セキュリティ ストアのユーザとグループを返し、完了時にセキュリティ ストアのリソースを解放する列挙値クラスを定義するコード

  4. カスタム セキュリティ レルムのクラスを定義するコード

  5. セキュリティ ストアに関するコンフィグレーション データを取得するコード

  6. ユーザを認証するコード

  7. グループのメンバーを返し、グループのメンバーを含むハッシュ テーブルを作成するコード

  8. ユーザ名が指定された User オブジェクトを返すコード

  9. グループ名が指定された Group オブジェクトを返すコード

  10. ユーザの列挙値を使用してセキュリティ ストアの全ユーザの User オブジェクトを返すコード

  11. グループの列挙値を使用してセキュリティ ストアの全グループの Group オブジェクトを返すコード

認可をサポートするカスタム セキュリティ レルムを記述することもできます。詳細については、 カスタム セキュリティ レルムでの認可の使い方を参照してください。

注意: WebLogic Server では、WebLogic Server Administration Console で管理可能なカスタム セキュリティ レルムを作成することもできます。詳細については、weblogic.security.acl パッケージの Javadoc を参照するか、BEA プロフェッショナル サービスにお問い合わせください。

カスタム セキュリティ レルムから別のサーバに対する RMI 呼び出しを実行しないでください。RMI 呼び出しを使うと、サーバのソケット リーダー スレッドが不足するおそれがあります。

表 4-4 は、カスタム セキュリティ レルムの作成に使用される WebLogic クラスを示しています。

表4-4 カスタム セキュリティ レルムの作成に使用される WebLogic クラス

クラス

定義

weblogic.security.acl.User

ローカル セキュリティ ストアから取得されるユーザを定義する。

weblogic.security.acl.
FlatGroup

ローカル セキュリティ ストア更新時にメンバシップが更新されるグループを定義する。

weblogic.security.acl.
CloseableEnumeration

閉じた後にリソースを解放できる列挙値を定義する。

weblogic.security.acl.
AbstractListableRealm

ユーザ、グループ、ACL、およびパーミッションを Admission Console で表示できるセキュリティ レルムの作成を可能にする。ただし、使用しているセキュリティ ストアによって提供される機能を使用して、ユーザ、グループ、ACL を追加および削除し、ユーザとグループにパーミッションを割り当てる必要がある。

weblogic.security.acl.
RefreshableRealm

Administration Console に表示されるユーザ、グループ、ACL、パーミッションに関する情報と、ローカル セキュリティ ストアの情報との同期を取る。

weblogic.management.
configuration.
CustomRealmMbean

カスタム セキュリティ レルムからアクセスされるセキュリティ ストアに関するコンフィグレーション情報を取得する。


 

図 4-1 は、これらのクラスを組み合わせてどのようにカスタム セキュリティ レルムを作成するかを示しています。

図4-1 カスタム セキュリティ レルムの作成に使用する WebLogic クラス


 

以降の節では、セキュリティ レルムの記述とカスタマイズに必要なプログラミング タスクについて説明します。

User クラスの定義

weblogic.security.acl.User クラスを拡張してカスタム セキュリティ レルムの User クラスを作成します。

コード リスト 4-13 は、User クラスを定義するコードを示しています。

コード リスト 4-13 User クラスの定義

// 必要なクラスをインポートする
import weblogic.security.acl.user;
...

// カスタム レルムのカスタム User クラスを作成
  /*package */class CustomRealmUser
  extends User
 {
  // ユーザのカスタム レルムを追跡
  CustomRealm realm = null;

  // コンストラクタを実装する
  /*package*/ CustomRealmUser(String name, CustomRealm realm);

  {
  // ユーザの名前を渡す基本コンストラクタを
  // 呼び出す
  super(name);

  // このユーザのレルムを追跡
  this.realm = realm;
  }
  // ユーザのカスタム レルムを返す
  public BasicRealm getRealm()
  {
  return realm;
  }
  }
...

Group クラスの定義

グループによってセキュリティの管理が容易になります。カスタム セキュリティ レルムの内部では、グループは、ユーザまたはグループになるメンバーのリストを格納するハッシュ テーブルとして表されます。

カスタム セキュリティに Group クラスを実装するには、weblogic.security.acl.Flatgroup クラスを拡張し、メンバシップ情報が定義されていない新しい Group クラスを作成します。クラスのコンストラクタは、カスタム セキュリティ レルムに対応する目的のグループとレルム オブジェクトの名前を入力値として取得します。

Flatgroup クラスは、カスタム セキュリティ レルムで動作するように特に設計されています。カスタム セキュリティ レルムは定期的にグループ メンバシップを更新します。FlatGroup では、静的セットの代わりにキャッシュにグループ メンバシップを保持します。キャッシュの期限が切れると、グループ実装はセキュリティ ストアに問い合わせて最新のメンバシップ情報を取得します。デフォルトのグループのキャッシュ時間は 5 分です。つまり、基になるストアを変更すると、5 分以内にカスタム セキュリティ レルムで認識されます。この値は、Administration Console の [グループ メンバシップ キャッシュ 生存時間] フィールドの値を、グループがキャッシュに保持される秒数に設定して調整します。

コード リスト 4-14 は、Group クラスを定義するコードを示しています。

コード リスト 4-14 Group クラスの定義

// 必要なクラスをインポートする
import weblogic.security.acl.FlatGroup;
...

/*package*/ class CustomRealmGroup
extends FlatGroup
{
  // コンストラクタを実装する
  /*package*/ CustomRealmGroup(String name,
  CustomRealm realm);
  {
  // グループとカスタム セキュリティ レルムの名前を
  // 渡す基本クラスのコンストラクタを呼び出す
  super(name, source);
  }
  // カスタム セキュリティ レルムの User クラスを返す
  // Group クラスを使用
  protected Class getUserClass()
  {
return CustomRealmUser.class;
  }
}
...

ユーザとグループの列挙値クラスの定義

ユーザとグループの列挙値クラスを記述します。列挙値が、列挙の完了時に解放する必要があるリソース(たとえば、データベース カーソル)を保持している場合は、weblogic.security.acl.CloseableEnumeration クラスを実装します。それ以外の場合は java.util.Enumeration インタフェースを実装します。列挙値のコンストラクタでは、セキュリティ ストアへのアクセスに必要な引数を渡します。

カスタム セキュリティ レルムでユーザまたはグループごとに User オブジェクトまたは Group オブジェクトを作成し、それを列挙するハッシュ テーブルに配置しないでください。デプロイされた WebLogic Server のカスタム セキュリティ レルムは、メモリの許容分より多くのユーザとグループを保持することがあります。代わりに、必要に応じて徐々に User オブジェクトまたは Group オブジェクトを作成できるデータベース カーソルを使用します。

コード リスト 4-15 は、ユーザとグループの列挙値クラスを定義するコードを示しています。

コード リスト 4-15 ユーザとグループの列挙値クラスの定義

// 必要なクラスをインポートする
import weblogic.security.acl.FlatGroup;
import weblogic.security.acl.ClosableEnumeration;

...
// ユーザの列挙値クラスを定義
/*package*/ class CustomRealmUsersEnumeration
implements CloseableEnumeration
{
  // ここにデータ メンバー(データベース カーソルなど)を保持

  // 列挙値のセキュリティ レルムを追跡
  // (User コンストラクタで使用する場合)
  private CustomRealm realm = null;

  // コンストラクタを実装する
  /*package */ CustomRealmUsersEnumeration(...,
CustomRealm realm)
  {
  this.realm = realm;
  }

  // より多くのユーザがいるかどうかを判別するメソッドを実装
  public boolean hasMoreElements()
  {
  // たとえば、データベース カーソルを使用して
  // より多くのユーザがいるかどうかを確認
  return (there are more users ...) ? true : false;
  }

  // 次のユーザを返すメソッドを実装
  // メソッドは、カスタム セキュリティ レルムの
  // User クラスを使用する User オブジェクトを返す
  public Object nextElement()
  {
  // たとえば、データベース カーソルを使用して
  // 次のユーザの名前を取得
  return new CustomRealmUser(next user name ..., realm);
  }

  // 列挙を終了するメソッドを実装
  // この手順は省略可能
  public void close()

  {
  // この列挙が、閉じる必要があるイテレータに
  // 委託している場合(データベース カーソルなど)、
  // ここでリソースを解放
  }
}

// カスタム セキュリティ レルムの Group クラスを作成
/*package*/class CustomRealmGroupsEnumeration
implements CloseableEnumeration
{
  // ここにデータ メンバー(データベース カーソルなど)を保持

  // 列挙値のセキュリティ レルムを追跡
  // (Group コンストラクタで使用する場合)
  private CustomRealm realm = null;

  // コンストラクタを実装する
  /*package */ CustomRealmUsersEnumeration(...,
CustomRealm realm)
  {
  this.realm = realm;
  }

  // より多くのグループがあるかどうかを判別するメソッドを実装
  public boolean hasMoreElements()
  {
  // たとえば、データベース カーソルを使用して
  // より多くのグループがあるかどうかを確認
  return (there are more groups ...) ? true : false;
  }

  // 次のグループを返すメソッドを実装
  // メソッドは、カスタム セキュリティ レルムの
  // Group クラスを使用する Group オブジェクトを返す
  public Object nextElement()
  {
  // たとえば、データベース カーソルを使用して
  // 次のグループの名前を取得する
  return new CustomRealmGroup(next group name ..., realm);
  }

  // 列挙を終了するメソッドを実装
  // この手順は省略可能
  public void close()

  {
  // この列挙が、閉じる必要があるイテレータに
  // 委託している場合(データベース カーソルなど)、
  // ここでリソースを解放
  }
}
...

カスタム セキュリティ レルムのクラスの定義

weblogic.security.acl.AbstractListableRealmクラスを拡張して、カスタム セキュリティ レルム用に新しいクラスを定義し、カスタム セキュリティ レルムを作成するコンストラクタを実装します。このクラスでは、以下の作業を行う必要があります。

  1. セキュリティ ストアに関するコンフィグレーション データを取得します。

  2. ユーザを認証します。

  3. グループのメンバーを決定します。

  4. セキュリティ ストアからユーザとグループを取得します。

WebLogic Server では、ユーザとグループの情報がメモリにキャッシュされます。したがって、カスタム セキュリティ レルムでは、ユーザとグループの情報が必要になるたびにディスクを参照するようお勧めします。WebLogic Server システム管理者は、セキュリティ ストアに付属のツールでストア内の情報を編集してカスタム セキュリティ レルムのユーザまたはグループを変更することのみが可能です。システム管理者は、セキュリティ ストア内のユーザまたはグループ情報を変更したら、Administration Console の [リセット] ボタンをクリックして情報を更新する必要があります。これによって、メモリに保持されているユーザとグループの情報が自動的にフラッシュされます。

カスタム セキュリティ レルムでユーザまたは グループの情報をメモリにキャッシュする場合は、weblogic.security.acl.RefreshableRealm クラスとこのクラスの refresh() メソッドを実装します。システム管理者がレルムをリセットすると、refresh() メソッドが呼び出されます。refresh() メソッドを使用すると、キャッシュされているユーザまたはグループ情報が破棄されます。

コード リスト 4-16 は、カスタム セキュリティ レルムのクラスを定義するコードを示しています。

コード リスト 4-16 カスタム セキュリティ レルムのクラスの定義

...
// 必要なクラスをインポート
import weblogic.security.acl.AbstractListableRealm;
import weblogic.security.acl.BasicRealm;
import weblogic.security.acl.RefreshableRealm;
import weblogic.server.Server;

// カスタム セキュリティ レルムのクラスを作成
public class CustomRealm
extends AbstractListableRealm // 必須
implements Refreshable Realm // 省略可能

// カスタム セキュリティ レルムを作成するコンストラクタを実装
public CustomRealm()
{
super("Custom Realm");
...

public void refresh()
{
// メモリ内のユーザおよびグループ情報を破棄
}

セキュリティ ストアに関するコンフィグレーション データの取得

セキュリティ ストアに接続するには、カスタム セキュリティ レルムで使用されるセキュリティ ストアにアクセスする方法を指定するコンフィグレーション プロパティ(URL を格納するプロパティやディレクトリ パスを指定するプロパティなど)を定義する必要があります。このプロパティを定義したら、WebLogic Server のシステム管理者は Administration Console の [新しい Custom Realm の作成] ウィンドウの [コンフィグレーション] タブでプロパティを設定します。セキュリティ ストアのプロパティを WebLogic Server の管理環境で定義してからカスタム セキュリティ レルムを使用する必要があります。

たとえば、ユーザとグループ情報を含むファイルへのパスを指定する userInfoFileNamegroupInforFileName という 2 つのプロパティを定義します。システム管理者は、Administration Console の [新しい Custom Realm の作成] ウィンドウの [コンフィグレーション] タブでそれらのプロパティを入力します。

カスタム セキュリティ レルムのコードで、weblogic.management.Helperおよびweblogic.management.configuration.DomainMbean クラスを使用してカスタム セキュリティのコンフィグレーション プロパティを取得し、そのプロパティの値を基にセキュリティ ストアに接続します。

コード リスト 4-17 は、セキュリティ ストアのコンフィグレーション プロパティを取得してセキュリティ ストアに接続するコードを示しています。

コード リスト 4-17 セキュリティ ストアへのアクセス

...
// 必要なクラスをインポート
import weblogic.management.Helper;
import weblogic.management.configuration.DomainMBean;

MBeanHome mHome = Helper.getMBeanHome(user, password, url,
servername);
DomainMBean domainMBean = mHome.getActiveDomain();
SecurityMBean secMBean = domainMBean.getSecurity();
BasicRealmMBean basicRealmMBean =
secMBean.getRealm().getCachingRealm.getBasicRealm();

CustomRealmMBean customRealmMBean =
(CustomRealmMBean)basicRealmMBean;

// CustomRealmMBean からコンフィグレーション データを取得
Properties configData = customRealmMBean.getConfigurationData();

// カスタム セキュリティ ストアのプロパティを取得
String userInfoFileName =
configData.getProperty("UserInfoFileName);
String groupInfoFileName =
configData.getProperty("GroupInfoFileName);

ユーザの認証

カスタム セキュリティ レルムでユーザをパスワード認証する場合は、authUserPassword() メソッドを明示的に実装する必要があります。authUserPassword() メソッドで指定したユーザが指定したパスワードで存在することを確認するためにセキュリティ ストアをチェックするコードを記述します。

コード リスト 4-18 は、ユーザを認証するコードを示しています。

コード リスト 4-18 ユーザの認証

...
// ユーザを認証するメソッドを実装
protected User authUserPassword(String name, String password)
{
  // セキュリティ ストアをチェックし、
  // パスワードが password name というユーザがいるかどうかを確認

  if (...) {
return new CustomRealmUser(name, this);
  } else {
return null;
  }
}

グループのメンバーの決定

weblogic.security.acl.AbstractListableRealm クラスの getGroupMembersInternal() メソッドを使用してグループのメンバーを取得し、グループのメンバーでハッシュ テーブルを構築します。

コード リスト 4-19 は、グループのメンバーを取得するコードを示しています。

コード リスト 4-19 グループのメンバーの取得

...
// グループのメンバーを返すメソッドを実装
protected Hashtable getGroupMembersInternal(String name)
{
// セキュリティ ストアをチェックし、指定した名前の
// グループがあるかどうかを確認
if (!...) {

// グループが存在しない場合は、例外を送出
throw new CustomRealmException("No such group : " + name);
}

// グループ メンバーを格納してから返されるハッシュ テーブルを
// 作成

Hashtable members = new Hashtable();

// セキュリティ ストアからグループのメンバーを取得
for (...) {// メンバーをループ処理
if (...) {
// このメンバーがユーザの場合、このユーザ用の
// User オブジェクトを作成して、それをメンバーのリストに追加
// カスタム セキュリティ レルム用に作成された
// User クラスを使用
members.put(memberName, new CustomRealmUser
(memberName, this));
} else if
// このメンバーがグループの場合、このグループ用の
// Group オブジェクトを作成して、それをメンバーのリストに追加
// カスタム セキュリティ レルム用に作成された
// User クラスを使用
members.put(memberName, new CustomRealmGroup
(memberName, this));
}
}
// グループのメンバーを格納するハッシュ テーブルを返す
return members;
}
...

セキュリティ ストアからのユーザとグループの取得

weblogic.security.acl.AbstractListableRealm クラスの getUser() メソッドと getGroup() メソッドを実装して、セキュリティ ストアのユーザとグループを取得し、カスタム セキュリティ レルムに取り込みます。weblogic.security.acl.AbstractListableRealm クラスの getUsers() メソッドと getGroups() メソッドを使用して、セキュリティ ストアのユーザとグループに対する User オブジェクトと Group オブジェクトを返す列挙オブジェクトを返します。セキュリティ ストア内のユーザとグループは Administration Console で表示できます。

コード リスト 4-20 は、セキュリティ ストアからユーザとグループを取得するコードを示しています。

コード リスト 4-20 セキュリティ ストアからのユーザとグループの取得

...
// 指定したユーザ名の User オブジェクトを返すメソッドを実装
public User getUser(String name)
{
// セキュリティ ストアをチェックし、指定した名前の
// グループがあるかどうかを確認
if (...) {
// ユーザがいる場合は、そのユーザの User オブジェクトを返す
// カスタム セキュリティ レルム用に作成された User クラスを使用
return new CustomRealmUser(name, this);
} else {
// ユーザがいない場合は null を返す
return null;
}
}

// 指定したグループ名の Group オブジェクトを返すメソッドを実装
public Group getGroup(String name)
{
// セキュリティ ストアをチェックし、指定した名前で
// グループがあるかどうかを確認
if (...) {
// グループがある場合は、そのグループの Group オブジェクトを返す
// カスタム セキュリティ レルム用に作成されたGroup クラスを使用
return new CustomRealmGroup(name, this
} else {
// グループがない場合は null を返す
return null;
}
}

// カスタム セキュリティ レルムで全グループに繰り返し処理を行うのに
// 使用できる列挙オブジェクトを返すメソッドを実装
public Enumeration getUsers()
{
// セキュリティ ストア内のユーザの User オブジェクトを返す列挙オブ
// ジェクトを返す
// カスタム セキュリティ レルム用に作成されたユーザ列挙クラスを使用
// 列挙値からセキュリティ ストアにアクセスできるようにすること
// それによって、複数のユーザに対して繰り返し処理が可能になる
return new CustomRealmUsersEnumeration(..., this);
}

// カスタム セキュリティ レルムで全グループに繰り返し処理を行うのに
// 使用できる列挙オブジェクトを返すメソッドを実装
public Enumeration getGroups()
{
// セキュリティ ストア内のグループの Group オブジェクトを返す列挙オブ
// ジェクトを返す
// カスタム セキュリティ レルム用に作成されたグループ列挙クラスを使用
// 列挙クラスからセキュリティ クラスにアクセスできるようにすること
// それによって複数のグループに対して繰り返し処理が可能になる
return new CustomRealmGroupsEnumeration(..., this);
}
...

注意: パフォーマンスを向上させるには、weblogic.security.acl.FlatGroup クラスの isMember() メソッドを使用します。このメソッドは、すべてのグループ メンバーをフェッチする代わりに、個別のユーザがグループのメンバーであるかどうかのチェックを行います。

カスタム セキュリティ レルムでの認可の使い方

カスタム セキュリティ レルムで ACL を作成するには、新しい AclImpl オブジェクトを作成し、名前を設定して、ユーザまたはグループごとに AclEntryImpl オブジェクトを追加します。各 AclEntry オブジェクトには、ユーザまたはグループを表す特定のプリンシパルに関連付けられた一連のパーミッションが格納されています。

AclImpl インタフェースでは、ACL の作成時に順序付け制約が強制的に適用されます。AclEntryImpl オブジェクトを AclImpl オブジェクトに追加する前に、AclEntryImpl オブジェクトにすべてのパーミッションを追加する必要があります。

カスタム セキュリティ レルムのクラスでは、getAcl() メソッドを使用してセキュリティ ストアから ACL を取得します。getAclInternal() メソッドでは、結果セットを基に AclImpl オブジェクトを作成し、ユーザとグループごとに AclEntryImpl オブジェクトを作成して、パーミッションを AclEntryImpl オブジェクトに追加します。AclEntryImpl オブジェクトが作成されると、AclImpl オブジェクトに追加されます。AclImpl オブジェクトが作成されると、getAclInternal() メソッドは完成した ACL を返します。

 


セキュリティ イベントの監査

weblogic.security.audit パッケージを使用すると、WebLogic Server セキュリティ レルムで発生するイベントに対して監査 SPI を使用できるようになります。パッケージには、インタフェース AuditProvider、および静的クラス Audit があります。WebLogic Server では、監査可能なセキュリティ イベントをこの 2 つに送信します。

監査を有効にするには、AuditProvider インタフェースを実装するクラス、および監査するセキュリティ イベントを示すメソッドを作成します。WebLogic Server では、ユーザが認証を試行する場合、パーミッションがテストされる場合、無効なデジタル証明書またはルート デジタル証明書が提示された場合に、クラスでメソッドが呼び出されます。AuditProvider クラスは、イベントのタイプごとに情報を受信し、ユーザが指定した方法でイベントを処理します。たとえば、失敗した認証リクエストだけを WebLogic Server ログ ファイルに記録することや、データベース テーブルに監査可能なイベントをすべて記録することなどが可能です。

AuditProvider クラスを使用する前に、Administration Console でクラスをインストールする必要があります。詳細については、「セキュリティの管理」の「監査プロバイダのインストール」を参照してください。

LoginAuditProvider サンプルは、\samples\examples\security\audit ディレクトリに収められている、WebLogic Server 付属の examples.security.audit パッケージにあります。サンプルでは、WebLogic Server ログ ファイルで受信する全イベントが記述されています。また、イベントのタイプごとにフィルタ メソッドを定義し、そのフィルタを呼び出して特定のイベントを記録するかどうかを決定しています。サンプル コードでは、フィルタ メソッドは全イベントが記録されるように常に true を返します。このサンプルを拡張する場合、記録するイベントを選択するメソッドでフィルタ メソッドをオーバーライドできます。ロギング以外の作業を行う場合は、LogAuditProvider サンプルを基に独自のプロバイダを作成できます。

 


ネットワーク接続のフィルタ処理

パスワード、ACL、デジタル証明書を使用すると、WebLogic Server リソースに対してユーザの性質に応じたセキュリティを適用できます。ネットワーク接続をフィルタ処理してセキュリティのレイヤを追加できます。たとえば、ユーザの企業のネットワーク外部からの非 SSL 接続を拒否できます。

ネットワーク接続をフィルタ処理するには、weblogic.security.net.ConnectionFilter インタフェースを実装するクラスを作成し、WebLogic Server にそのクラスをインストールします。それによって、受信したリクエストを調べ、それを受け付けるか拒否するかを決定できるようになります。

接続フィルタを使用する前に、Administration Console でクラスをインストールする必要があります。詳細については、「セキュリティの管理」の「接続フィルタのインストール」を参照してください。

Java クライアントまたは Web ブラウザ クライアントが WebLogic Server への接続を試行すると、WebLogic Server は ConnectionEvent オブジェクトを作成して、ConnectionFilter クラスの accept() メソッドに渡します。ConnectionEvent オブジェクトには、リモート IP アドレス(java.net.InetAddress という形式)、リモート ポート番号、ローカル WebLogic Server のポート番号、プロトコルを示す文字列(HTTP、HTTPS、T3、T3S、または IIOP)が格納されています。

ConnectionFilter クラスでは、ConnectionEvent オブジェクトを調べて、接続を受け付ける場合はオブジェクトを返し、接続を拒否する場合は FilterException を送出できます。

samples\examples\security\net ディレクトリにある、WebLogic Server 付属の examples.security.net.SimpleConnectionFilter サンプルでは、ルール ファイルで接続がフィルタ処理されています。SimpleConnectionFilter サンプルでは、ルール ファイルを解析してルールに適合するアルゴリズムを設定することで、WebLogic Server 接続のフィルタ処理のオーバーヘッドが最小化されています。SimpleConnectionFilter サンプルは、効率性を考慮した汎用接続フィルタです。必要に応じて、このコードを変更できます。たとえば、ローカルまたはリモートのポート番号を、フィルタ、またはフィルタ処理のオーバーヘッドを軽減するサイト固有のアルゴリズムに合わせることができます。

コード リスト 4-21 では、WebLogic Server は、ConnectionEvent を指定した SimpleConnectionFilter.accept() メソッドを呼び出しています。SimpleConnectionFilter.accept() メソッドは、リモート アドレスとプロトコルを取得してプロトコルをビットマスクに変換し、ルール適合時に文字列が比較されることを防ぎます。次に、SimpleConnectionFilter.accept() メソッドは、ルールごとにリモート アドレスとプロトコルを比較して、一致するものを見つけます。

コード リスト 4-21 ネットワーク接続のフィルタ処理の例

public void accept(ConnectionEvent evt)
throws FilterException
{
InetAddress remoteAddress = evt.getRemoteAddress();
String protocol = evt.getProtocol().toLowerCase();
int bit = protocolToMaskBit(protocol);

// この特殊なビットマスクは、
// 認識されたプロトコルのいずれかが接続で使用されないことを
// 示す
if (bit == 0xdeadbeef)
{
bit = 0;
}

// 記述された順でルールをチェック

for (int i = 0; i < rules.length; i++)
{
switch (rules[i].check(remoteAddress, bit))
{
case FilterEntry.ALLOW:
return;
case FilterEntry.DENY:
throw new FilterException("rule " + (i + 1));
case FilterEntry.IGNORE:
break;
default:
throw new RuntimeException("connection filter internal error!");
}
}

// 一致したルールがない場合でも、接続を成功させることができる

return;
}

 


SSL を使用した RMI over IIOP の使い方

SSL プロトコルを使用すると、RMI または EJB リモート オブジェクトへの IIOP 接続を保護できます。SSL プロトコルは、認証を通じて接続を保護し、オブジェクト間のデータ交換を暗号化します。WebLogic Server では、以下の方法で SSL を使用した RMI over IIOP を使用できます。

どちらの場合でも、SSL プロトコルを使用するよう、WebLogic Server をコンフィグレーションする必要があります。詳細については、「SSL プロトコルのコンフィグレーション」を参照してください。

CORBA クライアント ORB による SSL を使用した RMI over IIOP を使用するには、次の手順を行います。

  1. SSL プロトコルを使用するよう、CORBA クライアント ORB をコンフィグレーションします。SSL プロトコルのコンフィグレーションの詳細については、クライアント ORB の製品マニュアルを参照してください。

  2. host2ior ユーティリティを使用して、WebLogic Server IOR をコンソールに出力します。host2ior ユーティリティによって、SSL 接続用と非 SSL 用の 2 種類の IOR が出力されます。

  3. SSL IOR は、WebLogic Server JNDI ツリーにアクセスする CosNaming サービスへの初期参照を取得するときに使用します。

RMI over IIOP の使い方の詳細については、『WebLogic RMI Over IIOP プログラマーズ ガイド』を参照してください。

Java クライアントによる SSL を使用した RMI over IIOP を使用するには、次の手順を行います。

  1. コールバックを使用する場合は、Java クライアントのプライベート キーとデジタル証明書を取得します。

  2. SSL ソケット接続を処理するよう、java.rmi.server.RMISocketFactory クラスを拡張します。WebLogic Server が SSL 接続をリスンするポートを指定してください。java.rmi.server.RMISocketFactory クラスを拡張したクラスの例については、 コード リスト 4-22を参照してください。

  3. -d オプションを付けて ejbc コンパイラを実行します。

  4. java.rmi.server.RMISocketFactory クラスの拡張を、Java クライアントの CLASSPATH に追加します。

  5. Java クライアントを起動する場合は、次のコマンド オプションを使用します。

    -xbootclasspath/a:%CLASSPATH%
    -Dorg.omg.CORBA.ORBSocketFactoryClass=
    java.rmi.server.RMISocketFactory の実装
    -Dssl.certs= Java クライアントのデジタル証明書のパス
    -Dssl.key=Java クライアントのプライベート キーのパス

Java クライアントでは、CLASSPATH に含まれる SSL プロトコル用に WebLogic Server が使用するクラスが必要になります。

着信接続の場合(コールバックのための WebLogic Server から Java クライアントへの接続)、Java クライアントのデジタル証明書とプライベート キーをコマンドラインで指定する必要があります。ssl.certs および ssl.key というコマンドライン オプションを使用して、情報を入力します。 コード リスト 4-22 内の Java クライアントは、WebLogic Server の SSL ライブラリを使用して、SSL ソケットを提供しています。または、Sun Microsystems の JSSE などの SSL プロバイダを SSL ソケットとして使用することもできます。

コード リスト 4-22 java.rmi.server.RMISocketFactory の例

package examples.rmi_iiop.ejb.rmi_iiop;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.rmi.server.RMISocketFactory;
import java.util.StringTokenizer;
import java.util.Vector;
import weblogic.security.PEMInputStream;
import weblogic.security.RSAPrivateKey;
import weblogic.security.SSL.SSLCertificate;
import weblogic.security.SSL.SSLParams;
import weblogic.security.SSL.SSLServerSocket;
import weblogic.security.SSL.SSLSocket;
import weblogic.security.X509;

/**
*SSL プロトコルを使用するには、org.omg.CORBA.ORBSocketFactoryClass
*システム プロパティをexamples.rmi_iiop.ejb.rmi_iiop.SSLSocketFactory
*に設定する WebLogic Server から Java クライアントへの通信が必要になる場合
*(WebLogic Server で呼び出す必要のあるリモート オブジェクトを Java クラ
*イアントがエクスポートする場合など)もあるので、WebLogic Server で Java
*クライアントとの SSL 接続を確立できるよう、SSL プライベート キーとデジタル
*証明書の入力が必要になる場合もある**/

public class SSLSocketFactory extends RMISocketFactory

{
static int sslPort = 7002;

SSLCertificate cert;
RSAPrivateKey key;

private static InputStream getDERStream(String fileName)
throws IOException
{
InputStream is = new FileInputStream(fileName);

if (fileName.toLowerCase().endsWith(".pem")) {
is = new PEMInputStream(is);
}

return is;
}

public SSLSocketFactory()
{
String certFiles = System.getProperty("ssl.certs");
String keyFile = System.getProperty("ssl.key");

if (certFiles == null) {
System.err.println("Warning: no server certs (ssl.certs)
provided!");
System.err.println("Warning: incoming server connections
may fail!");
return;
}

if (keyFile == null) {
System.err.println("Warning: no server private key (ssl.key)
provided!");
System.err.println("Warning: incoming server connections
may fail!");
}

StringTokenizer toks = new StringTokenizer(certFiles,
System.getProperty("path.separator", ","));
cert = new SSLCertificate();
cert.certificateList = new Vector();

try {
if (keyFile != null) {
cert.privateKey = new
RSAPrivateKey(getDERStream(keyFile));
}

while (toks.hasMoreTokens()) {
InputStream is = getDERStream(toks.nextToken());
cert.certificateList.addElement(new X509(is));
is.close();
}
}

catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}

public Socket createSocket(String host, int port)
throws IOException
{
Socket sock = null;

System.out.println("*** connecting to " + host + ":" + port);

if (port == sslPort) {
try {
SSLParams p = new SSLParams();

sock = new SSLSocket(host, port, p);
}
catch (Exception e) {
e.printStackTrace();
}
}
else {
sock = new Socket(host, port);
}

return sock;
}

public ServerSocket createServerSocket(int i)
throws IOException
{
ServerSocket sock = null;

if (true) {
try {
SSLParams p = new SSLParams();

if (cert != null) {
p.setServerCert(cert);
}
else {
System.err.println
("**** Listening for SSL connections without server private key or certs!");

System.err.println
("**** THIS MAY CAUSE FAILURES IF THE SERVER
CONNECTS TO US!");
}

sock = new SSLServerSocket(i, p);
}
catch (Exception e) {
e.printStackTrace();
}
}
else {
sock = new ServerSocket(i);
}

int lp = sock.getLocalPort();
if (i != lp) {
System.out.println("*** listening on any port -
got " + lp);
}
else {
System.out.println("*** listening on port " + lp);
}

return sock;
}

}

 

back to top previous page