1

GlassFish 3.1.2.2 と Metro JAX-WS を使用してパートナー Web サービスに接続しようとしていますが、HTTP エラー 403.7 - 禁止されています: SSL クライアント証明書が必要です。

パートナーが提供した秘密鍵を GlassFish のキーストアにインポートしました。

$ keytool -importkeystore -srckeystore XXX.pfx -srcstoretype pkcs12 -destkeystore keystore.jks
$ keytool -changealias -alias "le-75e085d7-0ceb-4734-ac52-0e64646924c8" -destalias "XXX" -keystore keystore.jks
$ keytool -keypasswd -alias XXX -keystore keystore.jks

次に、GlassFish の domain.xml の httpsOutboundKeyAlias プロパティをこの新しいキーに設定します。

$ grep sas domains/dev/config/domain.xml
        <jvm-options>-Dcom.sun.enterprise.security.httpsOutboundKeyAlias=XXX</jvm-options>

次に、WS 呼び出しを行うと、次のようになります。

[#|2013-03-26T17:58:30.888-0700|INFO|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=137;_ThreadName=Thread-2;|#.: ---[HTTP request - https://XXX]---
Accept: text/xml, multipart/related
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://XXX"
User-Agent: Metro/2.2.0-1 (tags/2.2.0u1-7139; 2012-06-02T10:55:19+0000) JAXWS-RI/2.2.6-2 JAXWS/2.2 svn-revision#unknown
<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body>[...]</S:Body></S:Envelope>--------------------
|#]

[#|2013-03-26T17:58:31.847-0700|INFO|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=137;_ThreadName=Thread-2;|#.: ---[HTTP response - https://XXX - 403]---
null: HTTP/1.1 403 Forbidden
Content-Length: 1913
Content-Type: text/html
Date: Wed, 27 Mar 2013 00:58:31 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
[...]
<h2>HTTP Error 403.7 - Forbidden: SSL client certificate is required.<br>Internet Information Services (IIS)</h2>

この構成は他の Web サービスでは機能しますが、何らかの理由でこの構成では機能しません... IIS の動作が異なるかどうかわかりませんか?

opensslを使用してパートナーのpfxファイルから変換されたpemクライアント証明書を提示するcurlを使用して、正常に接続できるようです。

$ openssl pkcs12 -in XXX.pfx -out XXX.pem -nodes
$ curl -vk -E XXX.pem -H "Accept: text/xml, multipart/related" -H "Content-Type: text/xml; charset=utf-8" -H "SOAPAction: \"http://XXX\"" -d @req.xml  https://XXX

そのため、GlassFish/Metro が期待どおりにクライアント証明書を提示しない理由がわかりません。

不足している可能性があるものやトラブルシューティング方法についてのアイデア/提案はありますか?

-Djavax.net.debug=ssl を設定しようとしましたが、GlassFish ログに別のログ エントリとしてバイトが表示されるため、かなり判読できません。また、コンテナー外のスタンドアロン Java プログラムから実行しようとしましたが、クラスパスの問題が発生しました。

ありがとうございました

4

1 に答える 1

1

わかりました。後世のために、将来誰かを助ける場合に備えて: GlassFish のバグに絞り込みました。

javax.net.ssl ライブラリを使用して接続が機能するようになったため、何らかの理由で GlassFish は構成された httpsOutboundKeyAlias をその特定のサーバーに提供することを拒否します。他の人にとっては機能するため、具体的な理由は明らかではありませんが、ssl ログから、IIS サーバーがクライアント証明書の承認済み CA の長いリストを提供しているためと思われますか? リストが予想よりも長いか、GlassFish がクライアント証明書 CA を提供されたリストに一致させるのに問題がある可能性がありますか? GlassFish 開発者がこのバグを修正したい場合は、私に直接連絡してください。

とりあえず、それを機能させるためのコードは次のとおりです。

まず、提供されたクライアント証明書キー ストアを使用して、カスタム SSL ソケット ファクトリを作成します。

  KeyStore ebKeyStore = KeyStore.getInstance("PKCS12");
  try (InputStream clientCertKeyInput = new FileInputStream(pfxFilePath)) {
      ebKeyStore.load(clientCertKeyInput, passwdChars);
  }
  KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
  keyManagerFactory.init(ebKeyStore, passwdChars);

  SSLContext sslCtx = SSLContext.getInstance("TLS");
  sslCtx.init(keyManagerFactory.getKeyManagers(), 
              null, // default javax.net.ssl.trustStore
              new SecureRandom());

  sslSocketFactory = sslCtx.getSocketFactory();

次に、SOAP スタックがポートの RequestContext のプロパティを介してこの sslSocketFactory を使用するようにします。

    Map<String, Object> ctxt = ((BindingProvider) port).getRequestContext();
    ctxt.put(JAXWSProperties.SSL_SOCKET_FACTORY, sslSocketFactory);

希望の光は、GlassFish がクライアント証明書を提供するこの方法は、複数のアウトバウンド パーティに接続する必要がある場合に拡張できないことです。そのため、少なくともこのソリューションはこの問題も解決します。:)

于 2013-04-01T19:32:55.887 に答える