2012-04-21 43 views
49

私は、HTTPS SOAP WebサービスをJavaコードで呼び出すようです。私はすでにjre cacertsキーストアに自己署名証明書をインポートしています。今すぐ取得しています:SSLHandshakeException:サブジェクト代替名が存在しない

com.sun.xml.internal.ws.com.client.ClientTransportException: HTTP transport error: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present 

サービスURLのホスト名がcertで提供されているCNのホスト名と一致しません。カスタムホスト名検証ツールhereを定義する回避策についてお読みください。しかし私は自分のコードで回避策を実装すべき場所を作ることができません。

public SOAPMessage invokeWS(WSBean bean) throws Exception { 

    SOAPMessage response=null; 
    try{ 

    /** Create a service and add at least one port to it. **/ 
    String targetNameSpace = bean.getTargetNameSpace(); 
    String endpointUrl = bean.getEndpointUrl(); 
    QName serviceName = new QName(targetNameSpace, bean.getServiceName()); 
    QName portName = new QName(targetNameSpace, bean.getPortName()); 
    String SOAPAction = bean.getSOAPAction(); 
    HashMap<String, String> map = bean.getParameters(); 


    Service service = Service.create(serviceName); 
    service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointUrl); 

    /** Create a Dispatch instance from a service. **/ 
    Dispatch dispatch = service.createDispatch(portName, SOAPMessage.class, 
      Service.Mode.MESSAGE); 

    // The soapActionUri is set here. otherwise we get a error on .net based 
    // services. 
    dispatch.getRequestContext().put(Dispatch.SOAPACTION_USE_PROPERTY, 
      new Boolean(true)); 
    dispatch.getRequestContext().put(Dispatch.SOAPACTION_URI_PROPERTY, 
      SOAPAction); 

    /** Create SOAPMessage request. **/ 
    // compose a request message 
    MessageFactory messageFactory = MessageFactory.newInstance(); 
    SOAPMessage message = messageFactory.createMessage(); 

    // Create objects for the message parts 
    SOAPPart soapPart = message.getSOAPPart(); 
    SOAPEnvelope envelope = soapPart.getEnvelope(); 
    SOAPBody body = envelope.getBody(); 

    SOAPElement bodyElement = body.addChildElement(bean.getInputMethod(), 
      bean.getPrefix(), bean.getTargetNameSpace()); 

      ...more code to form soap body goes here 

    // Print request 
    message.writeTo(System.out); 

    // Save the message 
    message.saveChanges(); 

    response = (SOAPMessage)dispatch.invoke(message); 
    } 
    catch (Exception e) { 
     log.error("Error in invokeSiebelWS :"+e); 
    } 
    return response; 
} 

名前空間とその他のwsdl属性がこのBeanから来ているため、WSBeanパラメータを無視してください。この例外がいくつかの異なる回避策で解決できる場合は、plsが示唆しています。

+0

は、IPアドレスまたはホスト名を使用して、サービスのURIですか? – Bruno

+0

そのIPアドレスを使用しています。 – shashankaholic

答えて

82

ありがとう、ブルーノは私にコモンネームとサブジェクトの別名を付けてくれました。ネットワークのDNS名を持つCNで証明書が生成され、Subject Alternative Nameエントリ(san = ip:10.0.0.1)を持つ新しい証明書の再生成を求められました。のです。

しかし、開発段階で実行できるの回避策を見つけることができました。私たちがssl接続を作成しているクラスにスタティックブロックを追加するだけです。

static { 
    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() 
     { 
      public boolean verify(String hostname, SSLSession session) 
      { 
       // ip address of the service URL(like.23.28.244.244) 
       if (hostname.equals("23.28.244.244")) 
        return true; 
       return false; 
      } 
     }); 
} 

は、Java 8を使用することが起こる場合は、同じ結果を達成するための多くのスリッカー方法がある:

static { 
    HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> hostname.equals("127.0.0.1")); 
} 
+0

代わりに 'CN = localhost'を使って証明書を生成できました。 – Bruno

+1

OK。 MITMがそのIPアドレスで証明書を作成する可能性があるというわずかなリスクがあります(あなたが証明書と一致することを確認していないので)。これは、適切なCAが証明書をIPアドレスに発行することは考えられません。 – Bruno

+0

実際には、これは内部組織の開発のケースで、サーバーのメンバーはCA認定の証明書に行きたいと思っていないし、証明書を再生成するという苦痛(皮肉)を抱くことも望んでいない。ですから、クライアント側のコードでこれを微調整する必要があります。 – shashankaholic

28

一部のブラウザとは異なり、JavaはHTTPS仕様に厳密に準拠しています(RFC 2818、セクション3.1)およびIPアドレスになります。

ホスト名を使用する場合は、サブジェクトの代替名を使用する代わりに、サーバー証明書のサブジェクトDNの共通名にフォールバックすることができます。

IPアドレスを使用する場合は、証明書にサブジェクト代替名のエントリ(DNS名ではなくIPアドレスのタイプ)が必要です。

詳細については、this answerにその仕様とそのような証明書を生成する方法があります。

+0

thnks、私はこれは、自己署名証明書がサーバーで生成されたDNS名を使用していないので、理解しています。しかし、それは私のコントロールではないので、私はそれについて何もできません。私は間違った実行で悪いことができる回避策が必要ですが、atleastは時間のための私の問題を解決します。 – shashankaholic

+3

証明書のホスト名がアドレスに解決されない場合、サーバーは誤って構成されています。それにもかかわらず、あなたの '/ etc/hosts'ファイル(Linuxの場合、またはそれに相当するWindowsの場合)のこのIPアドレスにその名前を指すようにローカルDNS解決を変更することができます。 – Bruno

関連する問題