6

まず、すべての証明書を受け入れることはセキュリティがないと見なすことができることを知っていることを認めなければなりませんでした。「本物の」証明書がありますが、ライブシステムにのみあります。テストシステムの証明書は自己署名されています。そのため、開発中はテストサーバーを使用する必要があります。これにより、証明書を無効にする必要があります。

StackoverflowやWeb全体で、SSL証明書の受け入れという同じことをしようとしている多くのトップピックを見ました。しかし、私はをいじっていないので、これらの答えはどれも私の問題には当てはまらないようですHTTPSUrlConnections

私がリクエストを行っている場合、コードは通常次のようになります(明確にするためにコメントされています):

//creates an HTTP-Post with an URL
HttpPost post = createBaseHttpPost();
//loads the request Data inside the httpPost
post.setEntity(getHttpPostEntity());
//appends some Headers like user-agend or Request UUIDs
appendHeaders(post);

HttpClient client = new DefaultHttpClient();
//mResponse is a custom Object which is returned 
//from the custom ResponseHandler(mResponseHandler) 
mResponse = client.execute(post, mResponseHandler);
return mResponse;

私は自分自身TrustManagerとを注入する必要があることを読みましたX509HostnameVerivier。私はこれらを次のように作成しました:

private static final TrustManager[] TRUST_ALL_CERTS = new TrustManager[]{
        new X509TrustManager() {

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

            public void checkServerTrusted(X509Certificate[] chain, String authType)
                    throws CertificateException {
            }

            public void checkClientTrusted(X509Certificate[] chain, String authType)
                    throws CertificateException {
            }
        }

    };

    private static X509HostnameVerifier ACCEPT_ALL_HOSTNAMES = 
            new X509HostnameVerifier() {

                public void verify(String host, String[] cns, String[] subjectAlts)
                        throws SSLException {
                }

                public void verify(String host, X509Certificate cert) throws SSLException {
                }

                public void verify(String host, SSLSocket ssl) throws IOException {
                }

                public boolean verify(String host, SSLSession session) {
                    return true;
                }
            };

このようにリクエスト内に注入するとHostnameVerifier(クライアントは上からのDefaultHttpClientです)

SSLSocketFactory ssl = (SSLSocketFactory)client.getConnectionManager().getSchemeRegistry().getScheme("https").getSocketFactory();
ssl.setHostnameVerifier(ACCEPT_ALL_HOSTNAMES);

応答は「ホスト名**が一致しませんでした」から「不正な要求」に変わります。TrustManagerを設定する必要があると思いますが、検索したすべての場所で言及されているHttpsUrlConnectionsを使用していないため、リクエスト内のどこに設定するかわかりません。

4

1 に答える 1

9

いいえ、検証を無効にすることを強制するのではなく、検証を適切に実装することを強制します。すべての証明書をやみくもに受け入れないでください。いいえ、あなたの場合も同じです。Android がデフォルトで信頼していない証明書を信頼する必要があるだけです。

HttpClient を使用しているため、トラスト マネージャーを設定するための API は と多少異なりHttpsURLConnectionますが、手順は同じです。

  1. 信頼できる証明書 (サーバーの自己署名証明書) を含むキーストア ファイルをロードします。
  2. これでa を初期化KeyStoreします。
  3. from 2SocketFactoryを使用して を作成します。KeyStore
  4. SSL ソケットの作成時に HTTP クライアント ライブラリを使用するように設定します。

これは、Android のドキュメントで説明されています: http://developer.android.com/reference/org/apache/http/conn/ssl/SSLSocketFactory.html

この件に関するより詳細な記事では、トラスト ストア ファイルの作成方法が示されています

背景情報とコード例: http://nelenkov.blogspot.com/2011/12/using-custom-certificate-trust-store-on.html

これは、HttpClient を初期化するために必要なコードです。

KeyStore localTrustStore = KeyStore.getInstance("BKS");
InputStream in = getResources().openRawResource(R.raw.mytruststore);
localTrustStore.load(in, TRUSTSTORE_PASSWORD.toCharArray());

SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory
                .getSocketFactory(), 80));
SSLSocketFactory sslSocketFactory = new SSLSocketFactory(localTrustStore);
schemeRegistry.register(new Scheme("https", sslSocketFactory, 443));
HttpParams params = new BasicHttpParams();
ClientConnectionManager cm = 
    new ThreadSafeClientConnManager(params, schemeRegistry);

HttpClient client = new DefaultHttpClient(cm, params); 

この時点で、すべての証明書を信頼する言い訳はありません。もしそうなら、それはすべてあなた次第です:)

于 2012-12-18T02:59:34.973 に答える