2012-04-10 7 views
6

私はホスト名が間違っています.(いくつかのリンクから取得しました)を使用しました。私のプログラムは正常に動作しています。 「ホスト名が間違っている例外

public class Host { 

    public String subscribe() throws Exception { 
     String resp = ""; 
     String urlString="https://xxx.xxx.xx.xx:8443/WebApplication3/NewServlet"; 
     URL url; 
     URLConnection urlConn; 
     DataOutputStream printout; 
     DataInputStream input; 
     String str = ""; 
     int flag=1; 

     try { 
      HostnameVerifier hv = new HostnameVerifier() { 
       public boolean verify(String urlHostName, SSLSession session) { 
        System.out.println("Warning: URL Host: " + urlHostName + " vs. " 
         + session.getPeerHost()); 
        return true; 
       } 
      }; 

      trustAllHttpsCertificates(); 
      HttpsURLConnection.setDefaultHostnameVerifier(hv); 

      url = new URL(urlString); 
      urlConn = url.openConnection(); 
      urlConn.setDoInput(true); 
      Object object; 
      urlConn.setUseCaches(false); 

      urlConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 
      input = new DataInputStream(urlConn.getInputStream()); 

      while (null != ((str = input.readLine()))) { 
       if (str.length() >0) { 
        str = str.trim(); 
        if(!str.equals("")) { 
         //System.out.println(str); 
         resp += str; 
        } 
       } 
      } 
      input.close(); 
     } catch (MalformedURLException mue) { 
      mue.printStackTrace(); 
     } catch(IOException ioe) { 
      ioe.printStackTrace(); 
     } 
     return resp; 
    } 

    public static class miTM implements javax.net.ssl.TrustManager, 
     javax.net.ssl.X509TrustManager { 

     public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
      return null; 
     } 

     public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) { 
      return true; 
     } 

     public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) { 
      return true; 
     } 

     public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { 
      return; 
     } 

     public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { 
      return; 
     } 
    } 

    private static void trustAllHttpsCertificates() throws Exception { 

     // Create a trust manager that does not validate certificate chains: 
     javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1]; 

     javax.net.ssl.TrustManager tm = new miTM(); 

     trustAllCerts[0] = tm; 

     javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL"); 

     sc.init(null, trustAllCerts, null); 

     javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 

    } 

} 
+2

ご質問の一部としてコードを(コメント行なしで)掲載してください。 – MByD

+0

@Binyamin Sharet:私の質問の一部として投稿されたコード。 – user10101

+0

>私の質問は十分に安全ですか?<セキュリティは通常コンテキストと環境によって異なりますが、実際には測定できません。絶対的には、ホストに対する証明書を信頼するため、コードは安全ではありません。何らかの理由でDNSがハッキングされた場合、間違ったホストと話をする可能性があります。 –

答えて

4

miTMのコードは、実際に任意のSSLセキュリティチェックを無効にします(証明書チェーンを検証していないとして)、そのセキュリティレベルは、SSL証明書が壊れている場合にのみ、エラーが発生します(かなり低いですが、あなたはドン証明書がドメインと一致しない場合はエラーになりません)。

基本的には、セキュリティなしで接続しようとしています。それがあなたが望むなら、ソリューションは「十分に安全」かもしれませんが、おそらく答えは「いいえ」です。

この種の問題の正しい解決方法は、このドメインに一致する証明書を作成することです。

あなたのHTTPサーバが「仮想ホスティング」(=多くのドメイン名が同じIPアドレスにマップされている)を使用している場合、これは不可能です。この問題の正しい解決方法は、独自のIPアドレスを取得することです。

あなたはまだこの答えを見て、Javaで唯一の解決策を試してみたい場合:https://stackoverflow.com/a/3293720/34088

+0

:私もこのリンクを見ました...実際には、私のコードはリンクの1つに属しています( - > tutorialid = 211で終わります)。その解決策は何ですか? – user10101

+0

'trustAllHttpsCertificates()'を取り除く。 'HostnameVerifier'を設定すれば十分です。 –

+0

ちょうどラインtrustAllHttpsCertificates()にコメントしました。サービスメソッドで...機能の呼び出しを無効にするだけで十分ですか? – user10101

1

ここでは、あなたのコードをクリーンアップするために、安全なままにする方法です。コードが既知のサービス(信頼できる)に接続していると思います。ホスト名が一致しなくてもJava SSLスタックが接続を受け入れるようにするには、サーバー証明書をJVMトラストストアに追加するのが最善の方法です。

まず、ブラウザからサーバー証明書をエクスポートしてディスクに保存できます。 Linuxでは、openssl s_client -connect xxx.xxx.xx.xx:8443を使用して、ASCII形式のサーバ証明書をテキストファイルにコピー/ペーストすることができます。

は、その後のkeytool

keytool -import -alias myservice -file servercertificate.cer 

私が好む別のオプション、Javaが更新されたときに、あなた自身の場所にcacertsをコピーすることで、回帰を避けるためにjre/lib/security/cacerts JKSファイルにサーバー証明書をインポートし、それをjavax.net.ssl.trustStoreに感謝を宣言しますシステムプロパティ。

サーバー証明書がトラストストアにあるため、有効期限が切れるまで信頼されます。これは、自己署名入りサーバー証明書でよく使用されます。例外のような種類を取得するために使用するJavaで

1

多くの時間が

問題は、私はその適切なIPアドレスを使用して、証明書をインストールすることによってそれを解決した

ipconflict/IPドメインの不一致/無効な証明書である可能性があります。接続はあなたに(少なくとも)MUST確保ようにするに

1

:あなたは、これが1であることを確かに知っていない限り(ホスト名を確認

  • 、あなたが証明書を信頼していることを確認し

    • をし、おそらくあなたが信頼する証明書のみ)。

      • APIは、それがフォームを投げることを期待に対し、あなたが使用しているTrustManagerがすべてで証明書をチェックしません(それは、例外をスローすることはありません:あなたのコードは、これらの二つの点で失敗

      証明書が信頼されていない場合はCertificateException)。

    • ホスト名検証者は常にtrueを返します。

      • デフォルトの信頼マネージャーをしてください、またはあなた自身のトラストストアおよびデフォルトTrustManagerFactoryでそれらを初期化:あなたのコードを修正すること

    • デフォルトホスト名ベリファイアをそのまま使用します。

    あなたの質問(「ホスト名が間違っ例外」)のタイトルとあなたの例のURL https://xxx.xxx.xx.xx:8443を使用すると、IPアドレスに接続している示唆しているようです。

    型のdNSNameのsubjectAltName拡張が存在する場合、IDとして使用する必要があります。

    は、一部のブラウザとは異なり、Javaはかなり厳しく、この上の仕様(RFC 2818)を次の。それ以外の場合は、証明書のSubjectフィールドにある(最も固有の)Commonフィールド を使用する必要があります。 共通名の使用は既存の方法ですが、 が推奨されておらず、認証局は代わりに dNSNameを使用することをお勧めします。いくつかのケースでは

    [...]

    、URIは、IPアドレスではなくホスト名として指定されています。この場合、iPAddressのsubjectAltNameは証明書の中に でなければならず、URIのIPと正確に一致する必要があります。

    これは、サーバー証明書のSubject DNのCommon Name(CN)にIPアドレスを入力するだけでは解決できないことを意味します。 IPアドレスを使用している場合はに件名の代替名が必要です。 (Java 7以降、keytoolにはそのような証明書を生成するオプションがあります)

    this answerで使用するコマンドの詳細については、こちらをご覧ください。

    これは、IPアドレスを使用することは、たいていの場合、テスト環境では大部分しか動作しないということです。私は商用CAがあなたにIPアドレスベースの証明書を与えるとは思わない。 DNSエントリを設定することをお勧めします(テスト環境のファイルhostsの中にあっても)。

    IPアドレスを使用していない場合でも、その証明書がサーバーに接続しようとしているホスト名に対して有効であることを確認する必要があります。サブジェクト代替名のエントリがある場合は、ホスト名と一致する。それ以外の場合、ホスト名はこの証明書のSubject DNのCN RDNになければなりません。

  • 関連する問題