2011-08-19 21 views
14

2つのアプリケーションがあり、1つはサーブレット/ Tomcatサーバーで、もう1つはAndroidアプリケーションです。Android:HttpsURLConnectionを使用したHTTPS(SSL)接続

HttpURLConnectionを使用して、両方の間でXMLを送受信したいと考えています。

コード:

private String sendPostRequest(String requeststring) { 

    DataInputStream dis = null; 
    StringBuffer messagebuffer = new StringBuffer(); 

    HttpURLConnection urlConnection = null; 

    try { 
     URL url = new URL(this.getServerURL()); 

     urlConnection = (HttpURLConnection) url.openConnection();   

     urlConnection.setDoOutput(true); 

     urlConnection.setRequestMethod("POST"); 

     OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream()); 

     out.write(requeststring.getBytes()); 

     out.flush(); 

     InputStream in = new BufferedInputStream(urlConnection.getInputStream()); 

     dis = new DataInputStream(in); 

     int ch; 

     long len = urlConnection.getContentLength(); 

     if (len != -1) { 

      for (int i = 0; i < len; i++) 

       if ((ch = dis.read()) != -1) { 

        messagebuffer.append((char) ch); 
       } 
     } else { 

      while ((ch = dis.read()) != -1) 
       messagebuffer.append((char) ch); 
     } 

     dis.close(); 

    } catch (Exception e) { 

     e.printStackTrace(); 

    } finally { 

     urlConnection.disconnect(); 
    } 

    return messagebuffer.toString(); 
} 

は今、私はセキュリティのためのXMLSを送信するためにSSLを使用する必要があります。

まず、Java Keytoolを使用して.keystoreファイルを生成します。

Keytool -keygen -alias tomcat -keyalg RSA 

は、その後、私はその後、SSL

<Connector 
port="8443" protocol="HTTP/1.1" SSLEnabled="true" 
maxThreads="150" scheme="https" secure="true" 
keystoreFile="c:/Documents and Settings/MyUser/.keystore" 
keystorePass="password" 
clientAuth="false" sslProtocol="TLS" 
/> 

を使用するようにTomcatのserver.xmlファイルにXMLコードを入れて、私はそれをHttpsURLConnectionの

private String sendPostRequest(String requeststring) { 

    DataInputStream dis = null; 
    StringBuffer messagebuffer = new StringBuffer(); 

    HttpURLConnection urlConnection = null; 

    //Conexion por HTTPS 
    HttpsURLConnection urlHttpsConnection = null; 

    try { 
     URL url = new URL(this.getServerURL()); 

     //urlConnection = (HttpURLConnection) url.openConnection();   

     //Si necesito usar HTTPS 
     if (url.getProtocol().toLowerCase().equals("https")) { 

      trustAllHosts(); 

      //Creo la Conexion 
      urlHttpsConnection = (HttpsURLConnection) url.openConnection(); 

      //Seteo la verificacion para que NO verifique nada!! 
      urlHttpsConnection.setHostnameVerifier(DO_NOT_VERIFY); 

      //Asigno a la otra variable para usar simpre la mism 
      urlConnection = urlHttpsConnection; 

     } else { 

      urlConnection = (HttpURLConnection) url.openConnection(); 
     } 

//Do the same like up 

とtrustAllHostsを追加するためのHttpURLConnectionを変更しますすべてのサーバーを信頼する方法(証明書の確認は不要)

private static void trustAllHosts() { 

    X509TrustManager easyTrustManager = new X509TrustManager() { 

     public void checkClientTrusted(
       X509Certificate[] chain, 
       String authType) throws CertificateException { 
      // Oh, I am easy! 
     } 

     public void checkServerTrusted(
       X509Certificate[] chain, 
       String authType) throws CertificateException { 
      // Oh, I am easy! 
     } 

     public X509Certificate[] getAcceptedIssuers() { 
      return null; 
     } 

    }; 

    // Create a trust manager that does not validate certificate chains 
    TrustManager[] trustAllCerts = new TrustManager[] {easyTrustManager}; 

    // Install the all-trusting trust manager 
    try { 
     SSLContext sc = SSLContext.getInstance("TLS"); 

     sc.init(null, trustAllCerts, new java.security.SecureRandom()); 

     HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 

    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
} 

これらの変更は非常に効果的でしたが、すべてのサーバーを信頼する必要はありません。キーストアファイルを使用して接続を検証し、正しい方法でSSLを使用したいと考えています。 インターネットでたくさんのことを読んで、たくさんのテストをしましたが、私は自分がしなければならないことややり方を理解できません。

誰かが私を助けることができますか?

私の下手な英語のため申し訳ありません

非常

ありがとう------------------------- UPDATE 2011/08/24 ------------------------------------------------ -

まあ、私はまだこれに取り組んでいます。 (

private static void trustIFNetServer() { 

    try { 
     TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 

     KeyStore ks = KeyStore.getInstance("BKS"); 

     InputStream in = context.getResources().openRawResource(R.raw.mykeystore); 

     String keyPassword = "password"; 

     ks.load(in, keyPassword.toCharArray()); 

     in.close(); 

     tmf.init(ks); 

     TrustManager[] tms = tmf.getTrustManagers();  

     SSLContext sc = SSLContext.getInstance("TLS"); 

    sc.init(null, tms, new java.security.SecureRandom()); 

    } catch (Exception e) { 
    e.printStackTrace(); 
    } 
} 

まず私は鍵と証明書を持つ多くの問題があったが、今では働いている:私は

など、キーストア、InputStreamを設定するための新しい方法を作った方法は、このようになります。私はそうだと思う)

今私の問題はTimeOut例外です。私はなぜそれが生成されているのかわかりません。私はそれがデータ書き込みと何かだと思うが、私はまだ解決することはできません。

+0

あなたは、よく知られた認証局によって署名された証明書を使用していたり​​、自己署名証明書を使用していますか? –

答えて

6

hereのように、自己署名証明書の信頼ストアファイルを作成する必要があります。 クライアント側で使用して、サーバーに接続します。 JKSや別のフォーマットを使用するかどうかは関係ありません。今はJKSを想定しています。

あなたが気にしていることを達成するには、明らかに異なるTrustManagerが必要です。 TrustManagerFactoryを使用して、新しく作成したトラストストアでその信頼設定を入力することができます。

TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); 
KeyStore ks = KeyStore.getInstance("JKS"); 
FileInputStream in = new FileInputStream("<path to your key store>"); 
ks.load(in, "password".toCharArray()); 
in.close(); 
tmf.init(ks); 
TrustManager[] tms = tmf.getTrustManagers(); 

使用tmsあなたのSSL/TLS接続に使用される新しい信頼設定のための代わりにあなたのSSLContextを初期化します。

また、サーバーTLS証明書のCN部分がサーバーのFQDN(完全修飾ドメイン名)と等しいことを確認する必要があります。サーバーのベースURLが「https://www.example.com」の場合、証明書のCNは「www.example.com」である必要があります。これは、中間者攻撃を防ぐ機能であるホスト名検証に必要です。これを無効にすることができますが、これを使用する場合にのみ、接続は本当に安全です。

+0

私は彼がアンドロイドクライアントのトラストストアを正しく設定する必要があると思います。 –

+0

あなたは絶対に正しいです - 私はこれを変更します、ありがとう! – emboss

+0

助けてくれてありがとう。私はこれをすべて理解し、いくつかのテストをしようとします。どうもありがとうございました! –

0

トラストストアを作成し、資産として保管してから使用してください。SocketFactory。次に、あなた自身の「信頼する人」の代わりに工場を使用します。

+0

ありがとう、あなたはいくつかの例がありますか? –

+0

完全な例ではありませんが、トラストストア(サーバー証明書を含む)をロードした後は、パスワードとともにコンストラクタに渡してください。次に、結果の 'SocketFactory'インスタンスを' HttpsURLConnection.setDefaultSSLSocketFactory() 'に渡すことができます。 –

関連する問題