有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

javajavax。网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代码。请帮助我这里出了什么问题。我需要以不安全的方式连接,并允许在没有证书的情况下连接到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);
    }

共 (5) 个答案

  1. # 1 楼答案

    在尝试了本页上建议的大多数解决方案以及其他相关的stackoverflow讨论之后,我发现AJC的上述回应适用于ApacheHttpClient版本4.5

    原因: 在创建SSLConnectionSocketFactory时,如果在构造函数中未指定HostVerifier,则不会设置它并使用DefaultHostVerifier。所以AJC解决方案的第3行起了作用

    (至少这是apache httpclient 4.5.3中的行为)

  2. # 2 楼答案

    我花了一个小时试图解决同样的问题。这就是我的想法:

    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)

  3. # 3 楼答案

    这就是我想到的:

     SSLContextBuilder sslcontext = new SSLContextBuilder();
     sslcontext.loadTrustMaterial(null, new TrustSelfSignedStrategy());
     httpclient = HttpAsyncClients.custom().setSSLContext(sslcontext.build()).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
          .build();
    
  4. # 4 楼答案

    换掉这个

    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
    );
    
  5. # 5 楼答案

    感谢所有的解决方案。我已经在网上尝试了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);