2015-09-11 12 views
8

特定のサーバ(つまりhttps://serverexample.com/application/webservice?wsdl)を使用して正常に動作していたApache CXFでクライアントを作成しました。サーバ名表示(SNI)が必要なサーバのテストでApache CXFクライアントエラーが発生しました

しかし、サーバが別のIPに移動した、と今では同じIPでTLSおよびSNI(Serverの名前表示)を持つ2つのSSL証明書を持って、そして今、私たちのアプリケーションは、このエラーで失敗します。

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative DNS name matching serverexample.com found 

httpsが間違った証明書を取得している(別のサーバー名を持っている)ので、これが私のものと一致していないことがわかります。

私は、OpenSSLで起こって何かを見つけることを試みた、と私はサーバー名を入れている場合、URLにのみ動作します:

# openssl s_client -connect serverexample.com:443 -tls1 
Certificate chain 
0 s:/CN=otherserver.com/OU=Servers/O=MyOrganization/C=ES 
    i:/CN=ACV20/OU=PKACV/O=ACV/C=ES 

# openssl s_client -connect serverexample.com:443 -servername serverexample.com 
Certificate chain 
0 s:/CN=serverexample.com/OU=Servers/O=MyOrganization/C=ES 
    i:/CN=ACV220/OU=PKACV1/O=ACV2/C=ES 

エラーは、この時点で生成されたApacheのクライアントで起こった:

final URL wsdlURL = new URL("https://serverexample.com/application/webservice?wsdl"); 
final Operation_Service ss = new Operation_Service(wsdlURL, SERVICE_NAME); 

新しいOperation_Serviceで失敗します。

@WebServiceClient(name = "ENI.Operation", 
        wsdlLocation = "https://serverexample.com/application/webservice?wsdl", 
        targetNamespace = "http://inter.ra.es/awrp/wsdl") 
public class Operation_Service extends Service { 
    public final static URL WSDL_LOCATION; 
    public final static QName SERVICE = new QName("http://inter.ra.es/awrp/wsdl", "ENI.Operation"); 
    public final static QName Operation = new QName("http://inter.ra.es/awrp/wsdl", "ENI.Operation"); 
    static { 
     URL url = null; 
     try { 
      url = new URL("https://serverexample.com/application/webservice?wsdl"); 
     } catch (final MalformedURLException e) { 
      java.util.logging.Logger.getLogger(Operation_Service.class.getName()) 
       .log(java.util.logging.Level.INFO, 
        "Can not initialize the default wsdl from {0}", "https://serverexample.com/application/webservice?wsdl"); 
     } 
     WSDL_LOCATION = url; 
    } 

    public Operation_Service(final URL wsdlLocation, final QName serviceName) { 
     super(wsdlLocation, serviceName); 
    } 

javax.xml.ws.Serviceはjavax.xml.wsを呼び出します.spi.ServiceDelegate、org.apache.cxf.jaxwsのいくつかのクラスによって実装されているabastractクラスですが、ここで私はそれを失っています、私は何を見て良いのかわかりません...

私たちのクライアントはrunnringでjava 7.0とweblogic 12.1.1.0上のapache cxf 3.0.4。私はJava 6でSNIに問題があったと読んでいますが、ここでは7.0を使用しています。

私は何ができるのでしょうか。接続しようとしているservername(opensslのような)を示すためにjavaまたはクライアントにいくつかのオプションがありますか?

答えて

4

これは、JDK 1.8の「機能強化」と、サーバーに複数の証明書があることの組み合わせです。 JDK 1.8で壊れて何

は、ここで説明されています http://lea-ka.blogspot.com/2015/09/wtf-collection-how-not-to-add-api.html

それはこのように書き:

  • ませんSNI拡張が原因のバグhttps://bugs.openjdk.java.net/browse/JDK-8072464に送信されます。
  • サーバーは証明書「CN = otherserver.com」を返します。これには、おそらくSAN(SubjectAlternativeName)「otherserver.com」も含まれています。
  • JDKのデフォルトの「URLのなりすまし」チェックは完全に行われ、URLの「serverexample.com」と証明書の「otherserver.com」を比較します。 Ooops、例外はあります。

最も簡単修正は、すべてのWSDLおよびXSDファイルをダウンロードし、jarファイルのどこかにそれらをパッケージ化することです。

場合本当に、これは役立つかもしれないリモートサーバーからWSDLを取得する必要があります(「HTTPS

最終URLのwsdlURL =新しいURL://?otherserver.com /アプリケーション/ WebサービスのWSDL ");

しかし、 "/ application/webservice"は、rerexample.comにしか提供されていない可能性があるため、これは機能しない可能性があります。この場合、TLS接続とHTTP 404応答コードが取得されます。

これがうまくいかない場合は、あらゆる種類のSSLファクトリに頼らざるを得なくなります(冗長ですが、確かに可能です)。それらをjavax.ws ....クラスにフックしようとしますその部分は決してしなかった)。

+0

デフォルトのホスト名ベリファイアが変更されていないと思われるので、JDK-8072464が原因であるかどうかは疑問です。エンドポイント識別アルゴリズムが設定されているときにも失敗するかもしれない他のバグかもしれません。 CXFのケースではなく、カスタムファクトリでそれを処理する方法についてのいくつかの例です。 – jmd

+0

確かに、検証者は変更されません。しかし、他のコードでは、ホスト名ベリファイアが存在し、動作が異なることが分かります。それはすべてリンク先の記事で説明されています。 – user568826

0

希望あなたのために役立つ、この意志は: セットあなたのコードの初めにこのシステムプロパティ:

System.setProperty("jsse.enableSNIExtension", "false");

または

解決SSLハンドシェイク例外の

あなたは2つの方法を選択することができます

プログラムのVM引数を次のように設定します。-Djsse.enableSNIExtension=false

+0

いいえ、これは答えではありません。ここでは、クライアントがSNI拡張を送信することを望んでいますが、Javaはバグのためではありません。 – jmd

関連する問題