web-dev-qa-db-ja.com

HTTPSを使用したHttpGet:SSLPeerUnverifiedException

HttpClient を使用すると、HTTPSで通信しようとすると次のエラーが表示されます。

スレッド「メイン」javax.net.ssl.SSLPeerUnverifiedExceptionの例外:ピアが認証されていません。

ここに私のコードがあります:

URI loginUri = new URI("https://myUrl.asp");

HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet( loginUri );
HttpResponse response = httpclient.execute( httpget );

このエラーを抑制または削除するにはどうすればよいですか?

36
Stefan Kendall

HttpClient 3.xを使用して、これを行う必要があります。

Protocol easyHttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
Protocol.registerProtocol("https", easyHttps);

EasySSLProtocolSocketFactoryの実装は here にあります。

12
Stefan Kendall

注:実稼働コードではこれを行わず、代わりにhttpを使用するか、上記のように実際の自己署名付き公開キーを使用してください。

HttpClient 4.xxの場合:

import static org.junit.Assert.assertEquals;

import Java.security.KeyManagementException;
import Java.security.NoSuchAlgorithmException;
import Java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.Apache.http.HttpResponse;
import org.Apache.http.client.methods.HttpGet;
import org.Apache.http.conn.scheme.Scheme;
import org.Apache.http.conn.ssl.SSLSocketFactory;
import org.Apache.http.impl.client.DefaultHttpClient;
import org.junit.Test;

public class HttpClientTrustingAllCertsTest {

    @Test
    public void shouldAcceptUnsafeCerts() throws Exception {
        DefaultHttpClient httpclient = httpClientTrustingAllSSLCerts();
        HttpGet httpGet = new HttpGet("https://Host_with_self_signed_cert");
        HttpResponse response = httpclient.execute( httpGet );
        assertEquals("HTTP/1.1 200 OK", response.getStatusLine().toString());
    }

    private DefaultHttpClient httpClientTrustingAllSSLCerts() throws NoSuchAlgorithmException, KeyManagementException {
        DefaultHttpClient httpclient = new DefaultHttpClient();

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, getTrustingManager(), new Java.security.SecureRandom());

        SSLSocketFactory socketFactory = new SSLSocketFactory(sc);
        Scheme sch = new Scheme("https", 443, socketFactory);
        httpclient.getConnectionManager().getSchemeRegistry().register(sch);
        return httpclient;
    }

    private TrustManager[] getTrustingManager() {
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            @Override
            public Java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            @Override
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
                // Do nothing
            }

            @Override
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
                // Do nothing
            }

        } };
        return trustAllCerts;
    }
}
17
Jonas Andersson

この答えは、 owlstead および Mat の応答に続きます。 ME/mobile/Android SSLではなく、SE/EEインストールに適用されます。

誰もまだ言及していないので、これを修正する「生産方法」に言及します。 HttpClientのAuthSSLProtocolSocketFactoryクラス の手順に従って、トラストストアとキーストアを更新します。

  1. 信頼できる証明書をインポートし、トラストストアファイルを生成する

keytool -import -alias "my server cert" -file server.crt -keystore my.truststore

  1. 新しいキーを生成します(トラストストアと同じパスワードを使用します)

keytool -genkey -v -alias "my client key" -validity 365 -keystore my.keystore

  1. 証明書署名要求(CSR)を発行する

keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore

  1. (自己署名または証明書の署名を取得)

  2. 信頼できるCAルート証明書をインポートする

keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore

  1. 完全な証明書チェーンを含むPKCS#7ファイルをインポートします

keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore

  1. 結果のキーストアファイルの内容を確認します

keytool -list -v -keystore my.keystore

サーバー証明書がない場合は、JKS形式で証明書を生成してから、CRTファイルとしてエクスポートします。 ソース:keytool documentation

keytool -genkey -alias server-alias -keyalg RSA -keypass changeit
    -storepass changeit -keystore my.keystore

keytool -export -alias server-alias -storepass changeit
    -file server.crt -keystore my.keystore
16
Barett

この例外は、サーバーがJDK 7に基づいており、クライアントがJDK 6にあり、SSL証明書を使用している場合に発生します。 JDK 7ではsslv2helloメッセージハンドシェイクはデフォルトで無効になっていますが、JDK 6ではsslv2helloメッセージハンドシェイクが有効になっています。このため、クライアントがサーバーに接続しようとすると、sslv2helloメッセージがサーバーに送信され、sslv2helloメッセージが無効になっているため、この例外が発生します。これを解決するには、クライアントをJDK 7に移動するか、6u91バージョンのJDKを使用する必要があります。ただし、このバージョンのJDKを取得するには、

4
Tanuj Kumar

「secureClient」を返すメソッド(Java 7環境-NetBeans IDEおよびGlassFish Server:デフォルトでポートhttps 3920))、これが役立つことを願っています:

public DefaultHttpClient secureClient() {
    DefaultHttpClient httpclient = new DefaultHttpClient();
    SSLSocketFactory sf;

    KeyStore trustStore;
    FileInputStream trustStream = null;
    File truststoreFile;
    // Java.security.cert.PKIXParameters for the trustStore
    PKIXParameters pkixParamsTrust;

    KeyStore keyStore;
    FileInputStream keyStream = null;
    File keystoreFile;
    // Java.security.cert.PKIXParameters for the keyStore
    PKIXParameters pkixParamsKey;

    try {
        trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        truststoreFile = new File(TRUSTSTORE_FILE);
        keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keystoreFile = new File(KEYSTORE_FILE);
        try {
            trustStream = new FileInputStream(truststoreFile);
            keyStream = new FileInputStream(keystoreFile);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {
            trustStore.load(trustStream, PASSWORD.toCharArray());
            keyStore.load(keyStream, PASSWORD.toCharArray());
        } catch (IOException ex) {
            Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
        } catch (CertificateException ex) {
            Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {
            pkixParamsTrust = new PKIXParameters(trustStore);
            // accepts Server certificate generated with keytool and (auto) signed by Sun
            pkixParamsTrust.setPolicyQualifiersRejected(false);
        } catch (InvalidAlgorithmParameterException ex) {
            Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {
            pkixParamsKey = new PKIXParameters(keyStore);
            // accepts Client certificate generated with keytool and (auto) signed by Sun
            pkixParamsKey.setPolicyQualifiersRejected(false);
        } catch (InvalidAlgorithmParameterException ex) {
            Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {
            sf = new SSLSocketFactory(trustStore);
            ClientConnectionManager manager = httpclient.getConnectionManager();
            manager.getSchemeRegistry().register(new Scheme("https", 3920, sf));
        } catch (KeyManagementException ex) {
            Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnrecoverableKeyException ex) {
            Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
        }

    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
    } catch (KeyStoreException ex) {
        Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
    }
    // use the httpclient for any httpRequest
    return httpclient;
}
0
user2045005