Oracle® Fusion Middleware Oracle WebLogic Serverセキュリティのプログラミング 11g リリース1(10.3.4) B61619-02 |
|
前 |
次 |
この節では、以下の内容について説明します。
これらの節で参照するサンプル・コードは、WebLogic Server配布キットの次の場所から入手できます。
SAMPLES_HOME\server\examples\src\examples\security\sslclient
sslclient
ディレクトリには、instructions.html
ファイル、ant
ビルド・ファイル、および以下のJavaファイルとJavaServer Pageファイル(.jsp
)が含まれています。
MyListener.java
NulledHostnameVerifier.java
NulledTrustManager.java
SSLClient.java
SSLClientServlet.java
SSLSocketClient.java
SnoopServlet.jsp
以降の説明は、実際のサンプルを見ながら読み進めてください。
JSSE (Java Secure Socket Extension)は、SSLとTLS v1プロトコルをサポートおよび実装し、それらの機能をプログラム的に利用可能にするパッケージのセットです。WebLogic Serverは、WebLogic Serverクライアントとサーバー、Javaクライアント、Webブラウザ、および他のサーバーの間で転送されるデータを暗号化するためにSecure Sockets Layer (SSL)をサポートしています。
WebLogicクライアントではWebLogic ServerによるJSSEの実装を使用できますが、これは必須ではありません。他のJSSEの実装も、サーバーの外側のクライアント側のコードで同じように使用できます。
WebLogicのサーバー側アプリケーションでSSLを使用する際には、以下の制限が適用されます。
WebLogic Serverアプリケーションの開発における他の(サード・パーティの)JSSE実装の使用はサポートされていません。WebLogic Serverが使用するSSLの実装はサーバーの構成に対して固定であり、ユーザーのアプリケーションによって置き換えることはできません。
JSSEのWebLogic実装はJCE暗号サービス・プロバイダ(Cryptographic Service Provider : CSP)をサポートしていますが、プロバイダのJCEに対するサポートが一定していないため、テストされていないプロバイダがそのまま機能するかどうかは保証されていません。以下のプロバイダではWebLogic Serverをテスト済みです。
JDK 5.0に含まれているデフォルトJCEプロバイダ(SunJCEプロバイダ)。SunJCEプロバイダについては、http://java.sun.com/j2se/1.5.0/docs/guide/security/jce/HowToImplAJCEProvider.html
を参照してください。
nCipher JCEプロバイダ。
その他のプロバイダはWebLogic Serverで機能する可能性はありますが、テストされていないプロバイダの場合、おそらくそのままでは機能しません。WebLogic ServerでサポートされているJCEプロバイダの使用の詳細は、『Oracle WebLogic Serverの保護』のSSLの構成に関する項を参照してください。
WebLogic Serverでは、Secure Sockets Layer (SSL)で暗号化された通信にHTTPSポートを使用します。このポートはSSLにしか使用できません。
注意: WebLogicクライアントでセキュリティを実装するためには、JavaクライアントでWebLogic Serverソフトウェア配布キットをインストールする必要があります。 |
Javaクライアントは、Java Naming and Directory Interface (JNDI)を使用してWebLogic Serverに資格証明を渡します。Javaクライアントは、JNDI InitialContext
を取得してWebLogic Serverとの通信を確立します。その後、InitialContext
を使用して、WebLogic Server JNDIツリーで必要なリソースをルックアップします。
注意: JAASは認証方法として望ましい選択肢ですが、認証プロバイダのLoginModuleはユーザー名とパスワードの認証しかサポートしていません。したがって、クライアントの証明書認証(双方向SSL認証ともいう)ではJNDIを使用します。クライアントの証明書認証にJAASを使用するには、LoginModuleで証明書の認証を行うカスタム認証プロバイダを記述する必要があります。 |
ユーザーとユーザーの資格証明を指定するには、表5-1で示されているJNDIプロパティを設定します。
表5-1 認証に使用されるJNDIプロパティ
プロパティ | 意味 |
---|---|
INITIAL_CONTEXT_FACTORY |
エントリ・ポイントをWebLogic Server環境に提供します。クラスweblogic.jndi.WLInitialContextFactoryはWebLogic Server用のJNDI SPIです。 |
PROVIDER_URL |
ネーム・サービスを提供するWebLogic Serverのホストとポートを指定します。例: (t3sはSSLのWebLogic Server独自のバージョンです。) |
SECURITY_PRINCIPAL |
ユーザーがデフォルトの(アクティブな)セキュリティ・レルムに対して認証されているときのユーザーのIDを指定します。 |
SECURITY_CREDENTIALS |
ユーザーがデフォルトの(アクティブな)セキュリティ・レルムに対して認証されているときのユーザーの資格証明を指定します。 |
これらのプロパティは、InitialContext
コンストラクタに渡されるハッシュ表に格納されます。
例5-1は、Javaクライアントで一方向SSL証明書認証を使用する方法を示しています。双方向SSL認証のコード例については、例5-4を参照してください。
JNDIを使用する一方向SSL認証の例
... Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); env.put(Context.PROVIDER_URL, "t3s://weblogic:7002"); env.put(Context.SECURITY_PRINCIPAL, "javaclient"); env.put(Context.SECURITY_CREDENTIALS, "javaclientpassword"); ctx = new InitialContext(env);
注意: JNDIコンテキストとスレッド、およびJNDIコンテキストの潜在的な問題を回避する方法の詳細は、『Oracle WebLogic Server JNDIのプログラミング』のJNDIコンテキストとスレッドに関する項およびJNDIコンテキストの問題の回避方法に関する項を参照してください。 |
この節では、以下の内容について説明します。
WebLogic ServerでSSL認証を使用するJavaクライアントを実装するには、JDK 5.0アプリケーション・プログラミング・インタフェース(API)とWebLogic APIを組み合せて使用します。
表5-1では、証明書認証の実装に使用されるJava APIパッケージについて説明します。表5-1の情報はJava APIのドキュメントから取られており、WebLogic Server固有の情報がコメントで追加されています。Java APIの詳細は、http://java.sun.com/javase/6/docs/api/index.html
およびhttp://java.sun.com/javaee/5/docs/api
のJavadocを参照してください。
表5-1では、証明書認証の実装に使用されるWebLogic APIについて説明します。詳細については、WebLogicクラスのJavadocを参照してください。
表5-2 Java証明書API
Java証明書API | 説明 |
---|---|
javax.crypto( |
このパッケージは暗号操作のためのクラスとインタフェースを提供します。このパッケージで定義されている暗号操作には、暗号化、鍵の生成と照合、およびMessage Authentication Code (MAC)の生成が含まれます。 暗号化のサポートには、対称、非対称、ブロック、およびストリームの各暗号方式が含まれています。このパッケージは、セキュア・ストリームおよび暗号化されたオブジェクトもサポートしています。 このパッケージで提供されるクラスの多くは、プロバイダ・ベースです( |
このパッケージはネットワーク・アプリケーション用のクラスを提供します。ソケット作成用のファクトリが含まれています。ソケット・ファクトリを使うと、ソケットの作成と構成の動作をカプセル化できます。 |
|
javax.net.SSL( |
このパッケージのクラスとインタフェースはWebLogic Serverでサポートされていますが、WebLogic ServerでSSLを使用するときには |
java.security.cert( |
このパッケージは、証明書、証明書失効リスト(CRL)、および証明書パスの解析と管理を行うためのクラスとインタフェースを提供します。X.509 v3証明書およびX.509 v2 CRLのサポートが含まれています。 |
java.security.KeyStore( |
このクラスは、鍵と証明書のメモリー内コレクションを表します。以下の2タイプのキーストア・エントリの管理に使用されます。
|
java.security.PrivateKey( |
秘密鍵。このインタフェースには、メソッドまたは定数が含まれません。すべての秘密鍵インタフェースのグループ化(およびタイプ保証)を行う役割を持つのみです。 注意: 専用の秘密鍵インタフェースは、このインタフェースを拡張したものです。たとえば、 |
java.security.Provider( |
このクラスは、Java Security APIの「暗号サービス・プロバイダ」を表します。プロバイダは、以下のようなJava Securityの一部または全部を実装します。
各プロバイダには名前とバージョン番号が付いており、インストールされる各実行時において構成されます。 暗号サービスの実装を提供するには、開発者チームまたはサード・パーティのベンダーが実装コードを記述し、 |
javax.servlet.http.HttpServletRequest( |
このインタフェースは、 サーブレット・コンテナは、 |
javax.servlet.http.HttpServletResponse( |
このインタフェースは、 サーブレット・コンテナは、 |
javax.servlet.ServletOutputStream( |
このクラスは、バイナリ・データをクライアントに送信するための出力ストリームを提供します。 これは、サーブレット・コンテナが実装する抽象クラスです。このクラスのサブクラスは、 |
javax.servlet.ServletResponse( |
このクラスは、クライアントにレスポンスを送信する際にサーブレットを支援するオブジェクトを定義します。サーブレット・コンテナは、 |
表5-3 WebLogic証明書API
WebLogic証明書API | 説明 |
---|---|
リモートのオブジェクトにHTTP with SSL (HTTPS)を提示するのに使用されるクラスを提供します。このクラスは、クライアントとして機能しているWebLogic Serverから別のWebLogic ServerへのアウトバウンドSSL接続を確立するために使われます。 |
|
SSLハンドシェーク時のホスト名検証によって、URL内のホスト名がサーバーのID内のホスト名に一致するかどうかが検証されます。この検証は、介入者攻撃を防ぐために必要となります。 WebLogic Serverでは、HostnameVerifierの証明書ベースの実装がデフォルトで使用され、URLホスト名がサーバー証明書のCNフィールドと一致するかどうかが検証されます。 管理コンソールの「SSL」タブにある「詳細」ペインを使用すると、このデフォルトのホスト名検証をカスタム・ホスト名検証に変更できます。その場合、WebLogic SSL APIを使用しているサーバーで実行されているSSLクライアントのデフォルトに影響が生じます。また、 |
|
このインタフェースを使うと、ユーザーはピアの証明書チェーンでの何らかの検証エラーをオーバーライドし、ハンドシェークを継続できます。また、ピア証明書チェーンに対しさらに検証を実行し、必要に応じてハンドシェークを中断することもできます。 |
|
このクラスは、構成済みのCertPathValidationプロバイダを使用して、失効チェックなどの追加的な検証を実行します。 デフォルトでは、CertPathTrustManagerはインストールされますが、CertPathValidatorsを呼び出さないように構成されています(InboundCertificateValidationおよびOutboundCertificateValidationのSSLMBean属性で制御します)。 カスタムTrustManagerをインストールするアプリケーションでは、CertPathTrustManagerが置き換えられます。カスタムTrustManagerを使用するアプリケーションでCertPathProvidersも呼び出したい場合は、カスタムTrustManagerからCertPathTrustManagerに委任できます。 |
|
このクラスは、このコンテキスト下で作成されたすべてのソケットで共有されるすべての状態情報を保持します。 |
|
このクラスは、SSLソケットを作成するためのAPIを提供します。 |
|
このクラスは、コンテキスト要素名を定義します。SSLは、1つまたは複数のCertPathValidatorオブジェクトを呼び出して追加検証を実行する前に、一部の組込み検証を実行します。検証プロバイダは、実行済みの検証を検出することで、必要な検証の規模を縮小できます。 |
SSLクライアント・アプリケーションには、少なくとも以下のコンポーネントが含まれます。
Javaクライアント
通常、Javaクライアントは以下の機能を実行します。
クライアントID、信頼、HostnameVerifier
、およびTrustManager
によるSSLContext
の初期化
キーストアのロード、および秘密鍵と証明書チェーンの取得
SSLSocketFactoryの使用
WebLogic Serverのインスタンスによって提供されるJSPに接続するためのHTTPSの使用
HostnameVerifier
HostnameVerifierはweblogic.security.SSL.HostnameVerifier
インタフェースを実装します。
HandshakeCompletedListener
HandshakeCompletedListenerは、javax.net.ssl.HandshakeCompletedListener
インタフェースを実装します。このインタフェースは、SSLクライアントが、指定されたSSL接続に対するSSLハンドシェークの完了について通知を受け取るために使用します。
TrustManager
TrustManagerは、weblogic.security.SSL.TrustManager
インタフェースを実装します。
ここで説明しているコンポーネントを実装する完全な実践的SSL認証クライアントについては、WebLogic Serverで提供されているSAMPLES_HOME\server\examples\src\examples\security\sslclient
ディレクトリのSSLClientサンプル・アプリケーションを参照してください。
JSSE認証の詳細は、Sunの『Java Secure Socket Extension (JSSE) Reference Guide』(http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html
)を参照してください。
この節では、以下のトピックを取り上げます。
URLオブジェクトを使用すると、クライアントとして機能しているWebLogic Serverインスタンスから別のWebLogic ServerインスタンスへのアウトバウンドSSL接続を確立することができます。weblogic.net.http.HttpsURLConnection
クラスを使用して、秘密鍵とデジタル証明書を含む、クライアントのセキュリティ・コンテキスト情報を指定できます。
weblogic.net.http.HttpsURLConnection
クラスは、ネゴシエーションされた暗号スイートの判別、ホスト名検証の取得と設定、サーバーの証明書チェーンの取得、および新しいSSLソケットを作成するためのSSLSocketFactory
の取得と設定を行うメソッドを提供します。
SSLClientのサンプル・コードでは、weblogic.net.http.HttpsURLConnection
クラスを使用してアウトバウンドSSL接続を確立しています。SSLClientのサンプル・コードは、SAMPLES_HOME\server\examples\src\examples\security\sslclient
ディレクトリのexamples.security.sslclient
パッケージにあります。
ここでは、様々なタイプのSSLクライアントを作成する方法を、サンプルを使って説明します。以下のタイプのSSLクライアントについて説明します。
SSLClientサンプルでは、URL
およびURLConnection
オブジェクトによって発信SSL接続をWebLogic SSLライブラリを使用して確立する方法が示されています。スタンドアロンのアプリケーションからだけでなく、WebLogic Server内のサーブレットからこの処理を行う方法も示されています。
注意: SSLクライアントとして機能するWebLogic Serverでは、発信SSL接続にサーバーのID証明書を使用します。WebLogic Serverで実行するアプリケーションで以前に記述されたSSL APIを使用している場合、デフォルトではサーバーのID証明書は共有されません(信頼のみ)。 |
例5-2は、SSLClientサンプルの抜粋です。このサンプルは、SSLClient.java
ファイルのSAMPLES_HOME\server\examples\src\examples\security\sslclient
ディレクトリにあります。
例5-2 SSLClientサンプル・コードの抜粋
package examples.security.sslclient; import java.io.*; import java.net.URL; import java.security.Provider; import javax.servlet.ServletOutputStream; ... /* * This method contains an example of how to use the URL and * URLConnection objects to create a new SSL connection, using * WebLogic SSL client classes. */ public void wlsURLConnect(String host, String port, String sport, String query, OutputStream out) throws Exception { ... URL wlsUrl = null; try { wlsUrl = new URL("http", host, Integer.valueOf(port).intValue(), query); weblogic.net.http.HttpURLConnection connection = new weblogic.net.http.HttpURLConnection(wlsUrl); tryConnection(connection, out); } ... wlsUrl = new URL("https", host, Integer.valueOf(sport).intValue(), query); weblogic.net.http.HttpsURLConnection sconnection = new weblogic.net.http.HttpsURLConnection(wlsUrl); ...
SSLSocketClientサンプルでは、直接セキュア・ポートからWebLogic Serverのインスタンスによって提供されるJSPに接続し、その接続の結果を表示する方法を示します。以下の機能を実装する方法が示されています。
クライアントID、HostnameVerifier
、およびTrustManager
によるSSLContext
の初期化
キーストアのロード、および秘密鍵と証明書チェーンの取得
SSLSocketFactory
の使用
WebLogic Serverによって提供されるJSPに接続するためのHTTPSの使用
javax.net.ssl.HandshakeCompletedListener
インタフェースの実装
サンプルが接続するサーバーが目的のホスト上で稼働していることを確認するための、weblogic.security.SSL.HostnameVerifier
クラスのダミー実装の作成
例5-3は、SSLSocketClientサンプルの抜粋です。このサンプルは、SSLSocketClient.java
ファイルのSAMPLES_HOME\server\examples\src\examples\security\sslclient
ディレクトリにあります。(sslclient
ディレクトリにあるSSLClientServletサンプルは、SSLClientサンプルの簡単なサーブレット・ラッパーです)。
例5-3 SSLSocketClientサンプル・コードの抜粋
package examples.security.sslclient; import java.io.*; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.Certificate; import javax.net.ssl.HandshakeCompletedListener; import javax.net.ssl.SSLSocket; import weblogic.security.SSL.HostnameVerifier; import weblogic.security.SSL.SSLContext; import weblogic.security.SSL.SSLSocketFactory; import weblogic.security.SSL.TrustManager; ... SSLContext sslCtx = SSLContext.getInstance("https"); File KeyStoreFile = new File ("mykeystore"); ... // Open the keystore, retrieve the private key, and certificate chain KeyStore ks = KeyStore.getInstance("jks"); ks.load(new FileInputStream("mykeystore"), null); PrivateKey key = (PrivateKey)ks.getKey("mykey", "testkey".toCharArray()); Certificate [] certChain = ks.getCertificateChain("mykey"); sslCtx.loadLocalIdentity(certChain, key); HostnameVerifier hVerifier = null; if (argv.length < 3) hVerifier = new NulledHostnameVerifier(); else hVerifier = (HostnameVerifier) Class.forName(argv[2]).newInstance(); sslCtx.setHostnameVerifier(hVerifier); TrustManager tManager = new NulledTrustManager(); sslCtx.setTrustManager(tManager); System.out.println(" Creating new SSLSocketFactory with SSLContext"); SSLSocketFactory sslSF = (SSLSocketFactory) sslCtx.getSocketFactory(); System.out.println(" Creating and opening new SSLSocket with SSLSocketFactory"); // using createSocket(String hostname, int port) SSLSocket sslSock = (SSLSocket) sslSF.createSocket(argv[0], new Integer(argv[1]).intValue()); System.out.println(" SSLSocket created"); HandshakeCompletedListener mListener = null; mListener = new MyListener(); sslSock.addHandshakeCompletedListener(new MyListener()); ...
証明書認証では、WebLogic Serverは、リクエスト元のクライアントにデジタル証明書を送信します。クライアントは、デジタル証明書を調べて、本物かどうか、期限切れでないかどうか、認証元のWebLogic Serverインスタンスに一致しているかどうかを確認します。
双方向SSL認証(相互認証の一形態)を使用する場合は、リクエスト元のクライアントもデジタル証明書をWebLogic Serverに提示します。双方向SSL認証をするようWebLogic Serverのインスタンスを構成すると、指定した認証局からデジタル証明書を送信するようにリクエスト元のクライアントに要求できるようになります。WebLogic Serverでは、信頼性のある認証局によって署名されたデジタル証明書のみが受け付けられます。
双方向SSL認証を行うようWebLogic Serverを構成する方法の詳細は、『Oracle WebLogic Serverの保護』のSSLの構成に関する項を参照してください。
以降の節では、双方向SSL認証をWebLogic Serverに実装する様々な方法について説明します。
Javaクライアントの双方向SSL認証でJNDIを使用する場合、WebLogic JNDI Environment
クラスのsetSSLClientCertificate()
メソッドを使用します。このメソッドは、クライアント認証に対して、X.509デジタル証明書の秘密鍵と証明書チェーンを設定します。
デジタル証明書をJNDIに渡すには、DERエンコードされたデジタル証明書を格納するファイルで開かれているInputStreams
の配列を作成し、JNDIハッシュ表にその配列を設定します。配列内の最初の要素には、Javaクライアントの秘密鍵ファイルで開かれているInputStream
が格納されている必要があります。配列内の2番目の要素には、Javaクライアントのデジタル証明書ファイルで開かれているInputStream
が格納されている必要があります(このファイルにはJavaクライアントの公開鍵が含まれています)。追加要素として、ルート認証局のデジタル証明書、証明書チェーン内のデジタル証明書の署名者を格納できます。デジタル証明書がサーバーの信頼性のある認証局によって直接発行されない場合、WebLogic Serverは、証明書チェーンを使用してJavaクライアントのそのデジタル証明書を認証できます。
weblogic.security.PEMInputStreamクラスを使用すると、Privacy Enhanced Mail (PEM)ファイルに保存されているデジタル証明書を読み込むことができます。このクラスでは、base 64でエンコードされた証明書をPEMファイルからデコードするフィルタが提供されます。
例5-4は、Javaクライアントで双方向SSL認証を使用する方法を示しています。
例5-4 JNDIを使用する双方向SSL認証クライアントの例
import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import weblogic.jndi.Environment; import weblogic.security.PEMInputStream; import java.io.InputStream; import java.io.FileInputStream; public class SSLJNDIClient { public static void main(String[] args) throws Exception { Context context = null; try { Environment env = new Environment(); // set connection parameters env.setProviderUrl("t3s://localhost:7002"); // The next two set methodes are optional if you are using // a UserNameMapper interface. env.setSecurityPrincipal("system"); env.setSecurityCredentials("weblogic"); InputStream key = new FileInputStream("certs/demokey.pem"); InputStream cert = new FileInputStream("certs/democert.pem"); // wrap input streams if key/cert are in pem files key = new PEMInputStream(key); cert = new PEMInputStream(cert); env.setSSLClientCertificate(new InputStream[] { key, cert}); env.setInitialContextFactory(Environment.DEFAULT_INITIAL_CONTEXT_FACTORY); context = env.getInitialContext(); Object myEJB = (Object) context.lookup("myEJB"); } finally { if (context != null) context.close(); } } }
JNDIのgetInitialContext()
メソッドが呼び出されると、JavaクライアントとWebLogic Serverは、Webブラウザが相互認証を実行してセキュリティ保護されたWebサーバー接続を取得するのと同じ方法で相互認証を実行します。デジタル証明書を確認できない場合やJavaクライアントのデジタル証明書をデフォルトの(アクティブな)セキュリティ・レルムで認証できない場合、例外がスローされます。認証されたユーザー・オブジェクトはJavaクライアントのサーバー・スレッドに格納され、保護されたWebLogicリソースへのJavaクライアントのアクセスを管理する許可のチェックに使用されます。
WebLogic JNDI Environment
クラスを使用する場合、getInitialContext()
メソッドの呼出しごとに新しいEnvironment
オブジェクトを作成する必要があります。User
オブジェクトとセキュリティ資格証明を一度指定すると、ユーザーおよびユーザーに関連する資格証明はEnvironment
オブジェクトの設定に残ります。再設定を試みてJNDI getInitialContext()
メソッドを呼び出した場合は、元のユーザーと資格証明が使用されます。
Javaクライアントによる双方向SSL認証を使用する場合、WebLogic Serverは、クライアントJVMごとに一意のJava仮想マシン(JVM) IDを取得し、JavaクライアントとWebLogic Serverの間の接続が切断されないようにします。処理がないために接続がタイムアウトになるまで、JavaクライアントのJVMが実行されている間は接続が続行されます。Javaクライアントが新しいSSL接続を確実にネゴシエーションできる唯一の方法は、そのJVMを停止してJVMの他のインスタンスを実行することです。
例5-4のコードでは、weblogic.security.providers.authentication.UserNameMapper
インタフェースを実装するWebLogic IDアサーション・プロバイダの呼出しが生成されます。UserNameMapper
インタフェースを実装するクラスは、デジタル証明書が有効な場合にユーザー・オブジェクトを返します。WebLogic Serverでは、この認証されたユーザー・オブジェクトはWebLogic Server内のJavaクライアントのスレッドに格納されます。格納されたユーザー・オブジェクトは、以降の認可リクエストで、スレッドがデフォルトの(アクティブな)セキュリティ・レルムで保護されているWebLogicリソースにアクセスする際に使用されます。
注意: セキュリティ・プロバイダ・プラグインがシステム・クラスパスからロードされます。システム・クラスパスはカスタムweblogic.security.providers.authentication.UserNameMapperインタフェースの実装を指定する必要があります。 |
証明書ベースの認証を実行するIDアサーション・プロバイダが構成されていない場合、SSL接続のJVMで動作しているJavaクライアントは、新しいJNDI InitialContext
を作成し、JNDI SECURITY_PRINCIPAL
とSECURITY_CREDENTIALS
プロパティで新しいユーザー名とパスワードを指定することでWebLogic ServerユーザーのIDを変更できます。SSL接続後にJavaクライアントによって渡されたデジタル証明書は使用されません。新しいWebLogic Serverユーザーは、最初のユーザーのデジタル証明書でネゴシエーションしたSSL接続を使用し続けます。
証明書ベースの認証を実行するIDアサーション・プロバイダが構成されている場合、WebLogic Serverはデジタル証明書をJavaクライアントからUserNameMapper
インタフェースを実装するクラスへ渡し、UserNameMapper
クラスがデジタル証明書をWebLogic Serverユーザー名にマップします。したがって、証明書ベースのIDアサーションを使用していて新しいユーザーIDを設定する場合、そのIDは変更できません。この理由は、デジタル証明書は、Environment
ごとにJVMからの最初の接続リクエストの時点でのみ処理されるからです。
警告: 双方向SSLとJNDIを使用している場合は、1つのクライアントJVMから複数のユーザーが同時にWebLogic Serverにログインすることはできません。異なるスレッドで複数のログインが実行された場合、その結果は確認不能であり、片方のユーザーのリクエストが別のユーザーのログインで実行され、ユーザーが別のユーザーのデータにアクセスできるようになることも考えられます。WebLogic Serverでは、1つのクライアントJVMからの証明書ベースの複数の同時ログインをサポートしていません。JNDIコンテキストとスレッド、およびJNDIコンテキストの潜在的な問題を回避する方法の詳細は、『Oracle WebLogic Server JNDIのプログラミング』のJNDIコンテキストとスレッドに関する項およびJNDIコンテキストの問題の回避方法に関する項を参照してください。 |
双方向SSLを使用している場合、WebLogic ServerはSSL接続を確立するときにWebブラウザまたはJavaクライアントのデジタル証明書を確認します。ただし、デジタル証明書はWebブラウザまたはJavaクライアントをWebLogic Serverセキュリティ・レルムのユーザーとしては認識しません。WebブラウザまたはJavaクライアントがセキュリティ・ポリシーで保護されたWebLogic Serverリソースをリクエストすると、WebLogic ServerはWebブラウザまたはJavaクライアントにIDを持つように要求します。このリクエストに対応するため、WebLogic IDアサーション・プロバイダは、WebブラウザまたはJavaクライアントのデジタル証明書をWebLogic Serverセキュリティ・レルムのユーザーにマップするユーザー名マッパーを、有効にできるようにします。ユーザー名マッパーは、weblogic.security.providers.authentication.UserNameMapper
インタフェースの実装でなければなりません。
weblogic.security.providers.authentication.UserNameMapper
インタフェースのデフォルト実装、DefaultUserNameMapperImpl
を使用することも、独自の実装を開発することもできます。
WebLogic IDアサーション・プロバイダは、以下のIDアサーション・トークン・タイプについて、UserNameMapper
インタフェースの実装を呼び出すことができます。
SSLハンドシェークを通じて渡されたX.509デジタル証明書
CSIv2を通じて渡されたX.509デジタル証明書
CSIv2を通じて渡されたX.501識別名
その他のタイプの証明書をマップする場合は、UserNameMapper
インタフェースの独自の実装を記述します。
デジタル証明書をユーザー名にマップするUserNameMapper
インタフェースを実装するには、次の処理を実行するUserNameMapper
クラスを記述します。
UserNameMapper
実装クラスをインスタンス化します。
UserNameMapper
インタフェース実装を作成します。
mapCertificateToUserName()
メソッドを使用して、クライアントから提示された証明書チェーンに基づいて証明書をユーザー名にマップします。
文字列属性タイプを対応するAttribute Value Assertion
フィールド・タイプにマップします。
セキュリティ・プロバイダ・プラグインがシステム・クラスパスからロードされます。システム・クラスパスはweblogic.security.providers.authentication.UserNameMapperインタフェースの実装を指定する必要があります。
一方のWebLogic Serverインスタンスがもう一方のWebLogic Serverインスタンスのクライアントとして機能するサーバー間通信で双方向SSL認証を使用できます。サーバー間通信で双方向SSL認証を使用すると、一般的なクライアント/サーバー環境でない場合でも、信頼できる高度なセキュリティで保護した接続を利用することができます。
例5-5は、あるWebLogic Serverインスタンスで動作するサーブレットからserver2.weblogic.com
という別のWebLogic Serverインスタンスにセキュリティで保護された接続を確立する方法を示しています。
例5-5 他の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"); e.setInitialContextFactory ("weblogic.jndi.WLInitialContextFactory"); Context ctx = new InitialContext(e.getProperties())
例5-5で、WebLogic JNDI Environment
クラスは以下のパラメータを格納するハッシュ表を作成します。
setProviderURL
- SSLサーバーとして機能するWebLogic ServerインスタンスのURLを指定します。SSLクライアントとして機能するWebLogic Serverインスタンスは、このメソッドを呼び出します。URLでは、SSLを基にした、WebLogic Server独自のプロトコルであるt3sプロトコルを指定します。SSLプロトコルは、2つのWebLogic Serverインスタンス間の接続および通信を保護します。
setSSLClientCertificate
- SSL接続に使用する秘密鍵と証明書チェーンを指定します。このメソッドを使用して、秘密鍵(配列内の最初の入力ストリーム)とX.509証明書のチェーン(配列内の残りの入力ストリームを構成する)から成る入力ストリーム配列を指定します。証明書チェーン内の各証明書は、チェーン内の前の証明書の発行元です。
setSSLServerName
- SSLサーバーとして機能するWebLogic Serverインスタンスの名前を指定します。SSLサーバーがデジタル証明書をSSLクライアントとして機能するWebLogic Serverに提示すると、setSSLServerName
メソッドを使用して指定された名前がデジタル証明書内の一般名と比較されます。ホスト名検証が成功するためには、名前が一致する必要があります。このパラメータは、介入者攻撃を防ぐために使用されます。
setSSLRootCAFingerprint
- 信頼性のある認証局のセットを表すデジタル・コード(つまり、信頼性のある証明書のフィンガープリントに基づく信頼)を指定します。SSLサーバーとして機能するWebLogic Serverインスタンスから受け取った証明書チェーンのルート証明書は、このメソッドで指定されたフィンガープリントのいずれかと一致しないと信頼を確立できません。このパラメータは、介入者攻撃を防ぐために使用されます。これにより、WebLogic Serverの信頼構成でWebLogic Serverで動作するクライアント用に指定されているデフォルト・レベルの信頼を補完できます。
注意: JNDIコンテキストとスレッド、およびJNDIコンテキストの潜在的な問題を回避する方法の詳細は、『Oracle WebLogic Server JNDIのプログラミング』のJNDIコンテキストとスレッドに関する項およびJNDIコンテキストの問題の回避方法に関する項を参照してください。 |
Javaクライアントをサーブレット(または他のサーバー側Javaクラス)で認証するには、クライアントがデジタル証明書を提供したかどうかをチェックする必要があります。提供した場合は、証明書が信頼できる認証局で発行されたかどうかをさらにチェックします。サーブレットの開発者には、Javaクライアントが有効なデジタル証明書を持っているかどうかを尋ねる役割があります。WebLogic Servlet APIでサーブレットを開発する場合、HTTPServletRequest
オブジェクトのgetAttribute()
メソッドでSSL接続に関する情報にアクセスする必要があります。
以下の属性が、WebLogic Serverサーブレットでサポートされています。
javax.servlet.request.X509Certificate
java.security.cert.X509Certificate []
- X509証明書の配列を返します。
javax.servlet.request.cipher_suite
- HTTPSが使用する暗号スイートを表す文字列を返します。
javax.servlet.request.key_size
- 対称(バルク暗号化)キー・アルゴリズムのビット・サイズを表す整数(0、40、56、128、168)を返します。
weblogic.servlet.request.SSLSession
javax.net.ssl.SSLSession
- 暗号スイートを含むSSLセッション・オブジェクト、およびSSLセッション・オブジェクトが作成された日付と最後に使用された日付を返します。
デジタル証明書に定義されているユーザー情報にアクセスできます。javax.servlet.request.X509Certificate
属性を取得すると、情報はjava.security.cert.X509Certificate
型の配列になっています。配列をその型にキャストして証明書を調べるだけで済みます。
デジタル証明書には、以下のような情報が指定されています。
サブジェクト(保持者、オーナー)の名前と、そのサブジェクトのIDを一意に確認するために必要なその他の識別情報
サブジェクトの公開鍵
デジタル証明書を発行した認証局の名前
シリアル番号
デジタル証明書の有効期間(存続期間)(開始日と終了日で定義)
ホスト名検証を使用すると、SSL接続先のホストが予定していた通信先、または許可された通信先であることを確認できます。ホスト名検証は、WebLogicクライアントまたはWebLogic Serverインスタンスが別のアプリケーション・サーバーのSSLクライアントとして動作している場合に便利です。介入者攻撃(man-in-the-middle attack)を防ぐのに役立ちます。
注意: デモ用デジタル証明書はインストール時に生成されるので、WebLogic Serverソフトウェアがインストールされるシステムのホスト名を格納します。したがって、開発またはテスト目的でデモ用証明書を使用する場合は、ホスト名検証をオンのままにしておく必要があります。 |
WebLogic ServerのSSLハンドシェーク機能としてのデフォルトの動作は、SSLサーバーのデジタル証明書のサブジェクトDNにあるCNフィールドと、サーバーへの接続に使用するURL内のホスト名を比較することです。これらの名前が一致しない場合はSSL接続が中断されます。
SSL接続の中断は、サーバーのホスト名をデジタル証明書と照らし合わせて有効性を検証するSSLクライアントによって実行されます。デフォルト以外の動作が必要な場合は、ホスト名検証を無効にするか、カスタム・ホスト名検証を登録します。ホスト名検証を無効にすると、SSL接続は介入者攻撃に対して無防備な状態になります。
ホスト名検証は、以下の方法で無効にできます。
管理コンソールで、サーバー(たとえばmyserver
)の「キーストア& SSL」タブの「詳細オプション」にある「ホスト名の検証」フィールドで「なし」を指定します。
SSLクライアントのコマンド・ラインで、次の引数を入力します。
-Dweblogic.security.SSL.ignoreHostnameVerification=true
カスタム・ホスト名検証を記述できます。weblogic.security.SSL.HostnameVerifier
インタフェースではコールバック・メカニズムが提供されるため、このインタフェースを実装することで、URLのホスト名への接続を許可するかどうかについてのポリシーを指定できます。ポリシーは、証明書ベースにすることも、他の認証スキームに依存させることも可能です。
カスタム・ホスト名検証を使用するには、weblogic.security.SSL.HostnameVerifier
インタフェースを実装するクラスを作成し、サーバーのセキュリティIDに関する情報を取得するメソッドを定義します。
注意: このインタフェースは新しいスタイルの証明書を受け取り、非推奨になったweblogic.security.SSL.HostnameVerifierJSSEインタフェースにかわるものです。 |
カスタム・ホスト名検証を使用する前に、以下の方法で実装するクラスを指定する必要があります。
管理コンソールで、サーバー構成の「SSL」タブの「詳細」にある「カスタム・ホスト名の検証」フィールドに、このインタフェースを実装するクラスの名前を指定します。指定するクラスには、引数を取らないパブリック・コンストラクタが必要です。
コマンド・ラインに、次の引数を入力します。
-Dweblogic.security.SSL.hostnameVerifier=hostnameverifier
hostnameverifier
の値は、カスタム・ホスト名検証を実装するクラスの名前です。
例5-6 は、NulledHostnameVerifierサンプルの抜粋です。このサンプルは、NulledHostnameVerifier.java
ファイルのSAMPLES_HOME\server\examples\src\examples\security\sslclient
ディレクトリにあります。このサンプル・コードには、比較のために常にtrueを返すNulledHostnameVerifier
クラスが含まれています。このサンプルでは、WebLogic SSLクライアントは、サーバーのホスト名とデジタル証明書のSubjectDNとの比較に関係なく、どのSSLサーバーにも接続できます。
weblogic.security.SSL.TrustManager
インタフェースは以下を可能にします。
特定の証明書検証エラーを無視します
ピア証明書チェーンに対して追加の検証を実行します
注意: このインタフェースは新しいスタイルの証明書を受け取り、非推奨になったweblogic.security.SSL.TrustManagerJSSEインタフェースにかわるものです。 |
SSLクライアントがWebLogic Serverのインスタンスに接続すると、サーバーは認証のためにデジタル証明書チェーンをクライアントに提示します。提示されたチェーンに無効なデジタル証明書が含まれている場合もあります。SSL仕様では、クライアントが無効な証明書を検出した場合、SSL接続が中断されることになっています。TrustManager
インタフェースのカスタム実装を使用すると、どのような場合にSSLハンドシェークを継続するか(または中止するか)を制御できます。トラスト・マネージャを使用することで、特定の検証エラーを無視(必要に応じてカスタム検証チェックを実行)してから、ハンドシェークを継続するかどうかを決定できます。
トラスト・マネージャを作成するには、weblogic.security.SSL.TrustManager
インタフェースを使用します。このインタフェースには、証明書検証で使用する一連のエラー・コードが含まれています。また、必要に応じて、ピア証明書での付加的な検証を実行したり、SSLハンドシェークを中断したりできます。デジタル証明書の検証が済むと、weblogic.security.SSL.TrustManager
インタフェースがコールバック関数を使用して、デジタル証明書の検証結果をオーバーライドします。トラスト・マネージャのインスタンスは、setTrustManager()
メソッドを使用してSSLコンテキストに関連付けることができます。
トラスト・マネージャはプログラムでのみ設定できます。その使用は、管理コンソールやコマンド・ラインでは定義できません。
注意: 実行する検証によっては、トラスト・マネージャを使用するとパフォーマンスに影響します。 |
例5-7は、NulledTrustManagerサンプルの抜粋です。このサンプルは、NulledTrustManager.java
ファイルのSAMPLES_HOME\server\examples\src\examples\security\sslclient
ディレクトリにあります。SSLSocketClientサンプルでは、カスタム・トラスト・マネージャを使用します。SSLSocketClientでは、トラスト・マネージャでSSLContextを使用して新しいSSL接続を設定する方法が示されています。
例5-7 NulledTrustManagerサンプル・コードの抜粋
package examples.security.sslclient; import weblogic.security.SSL.TrustManager; import java.security.cert.X509Certificate; ... public class NulledTrustManager implements TrustManager{ public boolean certificateCallback(X509Certificate[] o, int validateErr) { System.out.println(" --- Do Not Use In Production ---\n" + " By using this NulledTrustManager, the trust in" + " the server's identity is completely lost.\n" + " --------------------------------"); for (int i=0; i<o.length; i++) System.out.println(" certificate " + i + " -- " + o[i].toString()); return true; } }
CertPathTrustManager(weblogic.security.SSL.CertPathTrustManager
)は、デフォルトのセキュリティ・レルムの構成済み証明書パス検証プロバイダを使用して、失効チェックなどの追加的な検証を実行します。
デフォルトでは、サーバーのアウトバウンドSSLで使用するアプリケーション・コードからは、組込みのSSL証明書検証にしかアクセスできません。しかし、管理者がサーバーに構成した追加の証明書検証にアクセスするために、アプリケーション・コードでCertPathTrustManagerを指定することは可能です。アプリケーション・コードにおいて証明書パス検証プロバイダも実行する場合は、アプリケーション・コードでCertPathTrustManagerを使用する必要があります。
このクラスは、以下の3つの方法で使用できます。
アウトバウンドSSLで検証プロバイダを使用することを示すスイッチがSSLMBeanに設定されている場合にのみ、Trust Managerが構成済みのCertPathValidatorsを呼び出します。つまり、管理者が構成したものに、検証を完全に委任することになります。この方法には、setUseConfiguredSSLValidation()
メソッドを使用します。これがデフォルトです。
Trust Managerが常に構成済みのCertPathValidatorsを呼び出します。この方法には、setBuiltinSSLValidationAndCertPathValidators()
メソッドを使用します。
Trust Managerは構成済みのCertPathValidatorsを呼び出しません。この方法には、setBuiltinSSLValidationOnly()
メソッドを使用します。
javax.net.ssl.HandshakeCompletedListener
は、指定されたSSL接続に対するSSLプロトコル・ハンドシェークの完了についてSSLクライアントが通知を受け取る方法を定義します。例5-8は、MyListenerサンプルの抜粋です。このサンプルは、MyListener.java
ファイルのSAMPLES_HOME\server\examples\src\examples\security\sslclient
ディレクトリにあります。
例5-8 MyListener (HandshakeCompletedListener)サンプル・コードの抜粋
package examples.security.sslclient; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.FileInputStream; import javax.net.ssl.HandshakeCompletedListener; import java.util.Hashtable; import javax.net.ssl.SSLSession; ... public class MyListener implements HandshakeCompletedListener { public void handshakeCompleted(javax.net.ssl.HandshakeCompletedEvent event) { SSLSession session = event.getSession(); System.out.println("Handshake Completed with peer " + session.getPeerHost()); System.out.println(" cipher: " + session.getCipherSuite()); Certificate[] certs = null; try { certs = session.getPeerCertificates(); } catch (SSLPeerUnverifiedException puv) { certs = null; } if (certs != null) { System.out.println(" peer certificates:"); for (int z=0; z<certs.length; z++) System.out.println(" certs["+z+"]: " + certs[z]); } else { System.out.println("No peer certificates presented"); } } }
SSLContext
クラスを使用すると、SSLをプログラムによって構成し、SSLセッション情報を保持できます。各インスタンスは、認証の実行に使用するキー、証明書チェーン、および信頼性のあるCA証明書を使用して構成できます。同じSSLContextで作成し、同じSSLサーバーへの接続に使用するSSLソケットは、SSLセッション情報を再利用できます。セッション情報が実際に再利用されるかどうかは、SSLサーバーによって異なります。
セッション・キャッシングの詳細は、『Oracle WebLogic Serverの保護』のSSLセッションの動作に関する項を参照してください。トラスト・マネージャ・クラスのインスタンスをSSLコンテキストと関連付けるには、weblogic.security.SSL.SSLContext.setTrustManager()
メソッドを使用します。
SSLContextは、プログラムでのみ設定できます。管理コンソールやコマンド・ラインでは設定できません。SSLContext
オブジェクトは、Javaのnew
式またはSSLContext
クラスのgetInstance()
メソッドで作成できます。getInstance()
メソッドは静的で、指定されたセキュア・ソケット・プロトコルを実装する新しいSSLContext
オブジェクトを生成します。SSLContext
クラスの使用例は、SAMPLES_HOME\server\examples\src\examples\security\sslclient
ディレクトリのSSLSocketClient.java
のサンプルで提供されています。SSLSocketClientサンプルでは、SSLContext
を使って新しいSSLソケットを作成する新しいSSLソケット・ファクトリを作成する方法が示されています。
例5-9は、getInstance()
メソッドを使用したインスタンス化のサンプルです。
URL
オブジェクトを使用すると、クライアントとして機能しているWebLogic Serverインスタンスから別のWebLogic ServerインスタンスへのアウトバウンドSSL接続を確立することができます。WebLogic Serverは、アウトバウンドSSL接続について一方向と双方向のSSL認証を両方ともサポートしています。
一方向SSL認証の場合は、java.net.URL
、java.net.URLConnection
、およびjava.net.HTTPURLConnection
クラスを使用して、URL
オブジェクトを使用するアウトバウンドSSL接続を確立します。例5-10は、HTTPおよびHTTPSのURLを両方ともサポートし、これらのJavaクラスのみを使用する(つまりWebLogicクラスは不要)simpleURL
クラスを示しています。WebLogic Serverで一方向SSL認証(HTTPS)にsimpleURL
クラスを使用するための必要条件は、java.protocols.handler.pkgs
のシステム・プロパティで「weblogic.net」
が定義されていることだけです。
注意: 例5-10 simpleURLサンプルは、デフォルトで信頼性とホスト名をチェックするため、このサンプルでは信頼されていてホスト名チェックを通過する実際のWebサーバーにデフォルトで接続する必要があります。そうしない場合は、コマンド・ライン上で信頼性とホスト名チェックをオーバーライドする必要があります。 |
例5-10 Javaクラスのみを使用する一方向SSL認証URLアウトバウンドSSL接続クラス
import java.net.URL; import java.net.URLConnection; import java.net.HttpURLConnection; import java.io.IOException; public class simpleURL { public static void main (String [] argv) { if (argv.length != 1) { System.out.println("Please provide a URL to connect to"); System.exit(-1); } setupHandler(); connectToURL(argv[0]); } private static void setupHandler() { java.util.Properties p = System.getProperties(); String s = p.getProperty("java.protocol.handler.pkgs"); if (s == null) s = "weblogic.net"; else if (s.indexOf("weblogic.net") == -1) s += "|weblogic.net"; p.put("java.protocol.handler.pkgs", s); System.setProperties(p); } private static void connectToURL(String theURLSpec) { try { URL theURL = new URL(theURLSpec); URLConnection urlConnection = theURL.openConnection(); HttpURLConnection connection = null; if (!(urlConnection instanceof HttpURLConnection)) { System.out.println("The URL is not using HTTP/HTTPS: " + theURLSpec); return; } connection = (HttpURLConnection) urlConnection; connection.connect(); String responseStr = "\t\t" + connection.getResponseCode() + " -- " + connection.getResponseMessage() + "\n\t\t" + connection.getContent().getClass().getName() + "\n"; connection.disconnect(); System.out.println(responseStr); } catch (IOException ioe) { System.out.println("Failure processing URL: " + theURLSpec); ioe.printStackTrace(); } } }
双方向SSL認証の場合は、weblogic.net.http.HttpsURLConnection
クラスを使用して、秘密鍵とデジタル証明書を含む、クライアントのセキュリティ・コンテキスト情報を指定できます。このクラスのインスタンスは、リモート・オブジェクトに対するHTTPS接続を表しています。
SSLClientサンプル・コード(例5-11)には、WebLogic URL
オブジェクトを使用して、アウトバウンドSSL接続を確立する方法が示されています。例5-11のサンプル・コードは、SAMPLES_HOME\server\examples\src\examples\security\sslclient
ディレクトリのSSLClient.java
ファイルからの抜粋です。
例5-11 WebLogic双方向SSL認証URLアウトバウンドSSL接続のサンプル・コード
wlsUrl = new URL("https", host, Integer.valueOf(sport).intValue(), query); weblogic.net.http.HttpsURLConnection sconnection = new weblogic.net.http.HttpsURLConnection(wlsUrl); ... InputStream [] ins = new InputStream[2]; ins[0] = new FileInputStream("clientkey.pem"); ins[1] = new FileInputStream("client2certs.pem"); String pwd = "clientkey"; sconnection.loadLocalIdentity(ins[0], ins[1], pwd.toCharArray());
WebLogic Serverソフトウェアには、完全な実践的SSL認証サンプルが付属しています。そのサンプルは、SAMPLES_HOME\server\examples\src\examples\security\sslclient
ディレクトリにあります。このサンプルの説明と、構築、構成、および実行の手順については、サンプル・ディレクトリのpackage.html
ファイルを参照してください。このサンプル・コードは、修正して再利用できます。