web-dev-qa-db-ja.com

javax.net.ssl.SSLPeerUnverifiedException:ホスト名がピアによって提供された証明書サブジェクトと一致しません

私はstackoverflowの多くのリンクをたどり、多くのソリューションを試しましたが、それらのどれも私のために働きませんでした。 WSO2 API managerバージョン1.9.1を使用しています。私は次のエラーに直面しています:

Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: Host name 'XXXXXXXXX' does not match the certificate subject provided by the peer (CN=localhost, O=WSO2, L=Mountain View, ST=CA, C=US)
    at org.Apache.http.conn.ssl.SSLConnectionSocketFactory.verifyHostname(SSLConnectionSocketFactory.Java:465)
    at org.Apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.Java:395)
    at org.Apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.Java:353)
    at org.Apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.Java:134)
    at org.Apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.Java:353)
    at org.Apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.Java:380)
    at org.Apache.http.impl.execchain.MainClientExec.execute(MainClientExec.Java:236)
    at org.Apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.Java:184)
    at org.Apache.http.impl.execchain.RetryExec.execute(RetryExec.Java:88)
    at org.Apache.http.impl.execchain.RedirectExec.execute(RedirectExec.Java:110)
    at org.Apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.Java:184)
    at org.Apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.Java:82)
    at org.Apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.Java:107)
    at com.Java.pushNotifications.WSO2DemoClient.main(WSO2DemoClient.Java:49)

次のJavaコードを開発しました。ここで何が間違っているのか助けてください。安全でない方法で接続し、certsなしでSSLサイトへの接続を許可する必要があります。

public static void main(String[] args) throws ClientProtocolException, IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        SSLContextBuilder builder = new SSLContextBuilder();
        builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());

        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", new PlainConnectionSocketFactory())
                .register("https", sslsf)
                .build();

        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
        cm.setMaxTotal(2000);//max connection

    CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf)
                .setConnectionManager(cm).build();

        HttpGet httpGet = new HttpGet("https://XXXXXXXXXX:8243/token");
        CloseableHttpResponse response = httpclient.execute(httpGet);

        String json =" {\"data\":\"grant_type=password&username=test&password=test123\"}";

        try {
            HttpPost httpost = new HttpPost(url);
            httpost.setHeader("Content-Type", "application/x-www-form-urlencoded");
            httpost.setHeader("Authorization", "Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");

            httpost.setEntity(new StringEntity(json));

            HttpResponse httpResponse = httpclient.execute(httpost);

            System.out.println(httpResponse.getStatusLine());
        }
        finally {
            response.close();
        }

        String responseString1 = new BasicResponseHandler().handleResponse(response);
        System.out.println("Response : "+responseString1);
    }
23
user5268786

同じ問題を修正するのに1時間かかりました。これは私が思いついたものです:

final SSLConnectionSocketFactory sslsf;
try {
    sslsf = new SSLConnectionSocketFactory(SSLContext.getDefault(),
            NoopHostnameVerifier.INSTANCE);
} catch (NoSuchAlgorithmException e) {
    throw new RuntimeException(e);
}

final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", new PlainConnectionSocketFactory())
        .register("https", sslsf)
        .build();

final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
cm.setMaxTotal(100);
httpClient = HttpClients.custom()
        .setSSLSocketFactory(sslsf)
        .setConnectionManager(cm)
        .build();

うまくいけば、機能し、非推奨のコードを使用しない(httpclient 4.4.1)。

41
antonpp

これを交換してください

CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf)
            .setConnectionManager(cm).build();

CloseableHttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(sslsf)
            .setConnectionManager(cm)
            .setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
            .build();

証明書が署名されていない場合(自己署名されていない場合)、次のことができます。

import Java.security.cert.CertificateException;
import Java.security.cert.X509Certificate;

public class TrustAllStrategy implements TrustStrategy {
    @Override
    public boolean isTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        return true;
    }
}

それから

builder.loadTrustMaterial(new TrustAllStrategy());

編集:これ

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            sslcontext, //for you this is builder.build()
            SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
);
15
EpicPandaForce

すべてのソリューションに感謝します。私は現在、1.5日間オンラインで利用可能なすべてのソリューションを試してきましたが、ようやく機能しました。ここに作業コードがあります

 SSLContextBuilder builder = new SSLContextBuilder();
 builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
 SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(builder.build(), NoopHostnameVerifier.INSTANCE);
 Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
            .register("http", new PlainConnectionSocketFactory())
            .register("https", sslConnectionSocketFactory)
            .build();

 PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
 cm.setMaxTotal(100);
 CloseableHttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(sslConnectionSocketFactory)
            .setConnectionManager(cm)
            .build();
 HttpPost httpPost = new HttpPost(url);
 httpPost.setEntity(postEntity);
 httpPost.expectContinue();
 CloseableHttpResponse response = httpclient.execute(httpPost);
10
AJC

これは私が思いついたものです:

 SSLContextBuilder sslcontext = new SSLContextBuilder();
 sslcontext.loadTrustMaterial(null, new TrustSelfSignedStrategy());
 httpclient = HttpAsyncClients.custom().setSSLContext(sslcontext.build()).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
      .build();
5
Dudi

このページで提案されているソリューションのほとんどと他の関連するstackoverflowの議論を試した後、AJCの上記の応答がApache httpclientバージョン4.5で機能することがわかりました。

理由:HostVerifierがコンストラクターで指定されていない場合、SSLConnectionSocketFactoryの作成中に設定されず、DefaultHostVerifierが使用されます。 AJCのソリューションの3行目が違いを生み出します。

(少なくともこれはApache httpclient 4.5.3の動作です)

3
Ashutosh