【问题标题】:Ignoring SSL certificate in Apache HttpClient 4.3忽略 Apache HttpClient 4.3 中的 SSL 证书
【发布时间】:2013-10-31 07:17:32
【问题描述】:

如何忽略 Apache HttpClient 4.3 的 SSL 证书(全部信任)?

我在 SO 上找到的所有答案都处理以前的版本,并且 API 发生了变化。

相关:

编辑:

  • 仅用于测试目的。孩子们,不要在家里(或在生产中)尝试

【问题讨论】:

    标签: java ssl apache-httpcomponents


    【解决方案1】:

    以下代码适用于信任自签名证书。创建客户端时必须使用TrustSelfSignedStrategy

    SSLContextBuilder builder = new SSLContextBuilder();
    builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            builder.build());
    CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(
            sslsf).build();
    
    HttpGet httpGet = new HttpGet("https://some-server");
    CloseableHttpResponse response = httpclient.execute(httpGet);
    try {
        System.out.println(response.getStatusLine());
        HttpEntity entity = response.getEntity();
        EntityUtils.consume(entity);
    } finally {
        response.close();
    }
    

    我没有故意包含SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER:重点是允许使用自签名证书进行测试,这样您就不必从证书颁发机构获得适当的证书。您可以使用正确的主机名轻松创建自签名证书,因此不要添加 SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER 标志。

    【讨论】:

    • 我必须在构造函数中添加参数 SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER 才能使其与 HttpClientBuilder 一起工作(如 holmis83 对 vasekt 的响应中所述)。
    • 也可以参考httpclient网站上的例子hc.apache.org/httpcomponents-client-4.3.x/httpclient/examples/…
    • 我还必须使用 ALLOW_ALL_HOSTNAME_VERIFIER:SSLConnectionSocketFactory(builder.build(), SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    • 这段代码适用于我没有使用带有参数SSLConnectionSocketFactory.ALLOW_‌​ALL_HOSTNAME_VERIFIER的弃用构造函数@
    • 我希望你已经指定了你正在使用的类的完整参考。 Idea 发现了多个名为SSLContextBuilder 的类。
    【解决方案2】:

    作为对@mavroprovato 答案的补充,如果您想信任所有证书而不仅仅是自签名,您会这样做(以您的代码风格)

    builder.loadTrustMaterial(null, new TrustStrategy(){
        public boolean isTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
            return true;
        }
    });
    

    或(从我自己的代码中直接复制粘贴):

    import javax.net.ssl.SSLContext;
    import org.apache.http.ssl.TrustStrategy;
    import org.apache.http.ssl.SSLContexts;
    
    // ...
    
            SSLContext sslContext = SSLContexts
                    .custom()
                    //FIXME to contain real trust store
                    .loadTrustMaterial(new TrustStrategy() {
                        @Override
                        public boolean isTrusted(X509Certificate[] chain,
                            String authType) throws CertificateException {
                            return true;
                        }
                    })
                    .build();
    

    如果你也想跳过主机名验证,你需要设置

        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(
                sslsf).setSSLHostnameVerifier( NoopHostnameVerifier.INSTANCE).build();
    

    也是。 (ALLOW_ALL_HOSTNAME_VERIFIER 已弃用)。

    强制性警告:您不应该这样做,接受所有证书是一件坏事。但是,您希望在一些罕见的用例中执行此操作。

    作为前面给出的代码的注释,即使 httpclient.execute() 抛出异常,您也需要关闭响应

    CloseableHttpResponse response = null;
    try {
        response = httpclient.execute(httpGet);
        System.out.println(response.getStatusLine());
        HttpEntity entity = response.getEntity();
        EntityUtils.consume(entity);
    }
    finally {
        if (response != null) {
            response.close();
        }
    }
    

    上面的代码是用

    测试的
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.3</version>
    </dependency>
    

    对于感兴趣的,这是我的完整测试集:

    import org.apache.http.HttpEntity;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.conn.ssl.NoopHostnameVerifier;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.ssl.SSLContextBuilder;
    import org.apache.http.ssl.TrustStrategy;
    import org.apache.http.util.EntityUtils;
    import org.junit.Test;
    
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.SSLHandshakeException;
    import javax.net.ssl.SSLPeerUnverifiedException;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    
    public class TrustAllCertificatesTest {
        final String expiredCertSite = "https://expired.badssl.com/";
        final String selfSignedCertSite = "https://self-signed.badssl.com/";
        final String wrongHostCertSite = "https://wrong.host.badssl.com/";
    
        static final TrustStrategy trustSelfSignedStrategy = new TrustSelfSignedStrategy();
        static final TrustStrategy trustAllStrategy = new TrustStrategy(){
            public boolean isTrusted(X509Certificate[] chain, String authType)
                    throws CertificateException {
                return true;
            }
        };
    
        @Test
        public void testSelfSignedOnSelfSignedUsingCode() throws Exception {
            doGet(selfSignedCertSite, trustSelfSignedStrategy);
        }
        @Test(expected = SSLHandshakeException.class)
        public void testExpiredOnSelfSignedUsingCode() throws Exception {
            doGet(expiredCertSite, trustSelfSignedStrategy);
        }
        @Test(expected = SSLPeerUnverifiedException.class)
        public void testWrongHostOnSelfSignedUsingCode() throws Exception {
            doGet(wrongHostCertSite, trustSelfSignedStrategy);
        }
    
        @Test
        public void testSelfSignedOnTrustAllUsingCode() throws Exception {
            doGet(selfSignedCertSite, trustAllStrategy);
        }
        @Test
        public void testExpiredOnTrustAllUsingCode() throws Exception {
            doGet(expiredCertSite, trustAllStrategy);
        }
        @Test(expected = SSLPeerUnverifiedException.class)
        public void testWrongHostOnTrustAllUsingCode() throws Exception {
            doGet(wrongHostCertSite, trustAllStrategy);
        }
    
        @Test
        public void testSelfSignedOnAllowAllUsingCode() throws Exception {
            doGet(selfSignedCertSite, trustAllStrategy, NoopHostnameVerifier.INSTANCE);
        }
        @Test
        public void testExpiredOnAllowAllUsingCode() throws Exception {
            doGet(expiredCertSite, trustAllStrategy, NoopHostnameVerifier.INSTANCE);
        }
        @Test
        public void testWrongHostOnAllowAllUsingCode() throws Exception {
            doGet(expiredCertSite, trustAllStrategy, NoopHostnameVerifier.INSTANCE);
        }
    
        public void doGet(String url, TrustStrategy trustStrategy, HostnameVerifier hostnameVerifier) throws Exception {
            SSLContextBuilder builder = new SSLContextBuilder();
            builder.loadTrustMaterial(trustStrategy);
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    builder.build());
            CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(
                    sslsf).setSSLHostnameVerifier(hostnameVerifier).build();
    
            HttpGet httpGet = new HttpGet(url);
            CloseableHttpResponse response = httpclient.execute(httpGet);
            try {
                System.out.println(response.getStatusLine());
                HttpEntity entity = response.getEntity();
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        }
        public void doGet(String url, TrustStrategy trustStrategy) throws Exception {
    
            SSLContextBuilder builder = new SSLContextBuilder();
            builder.loadTrustMaterial(trustStrategy);
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    builder.build());
            CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(
                    sslsf).build();
    
            HttpGet httpGet = new HttpGet(url);
            CloseableHttpResponse response = httpclient.execute(httpGet);
            try {
                System.out.println(response.getStatusLine());
                HttpEntity entity = response.getEntity();
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        }
    }
    

    (工作测试项目in github

    【讨论】:

    • HttpClient#execute 永远不会在出现异常的情况下返回空响应对象。此外,库存 HttpClient 实现将确保在请求执行期间发生异常时自动释放所有系统资源,例如租用的连接。 mavroprovato 使用的异常处理是完全足够的。
    • @oleg Closable interface 的意思是“关闭 [...] 流并释放与之关联的任何系统资源。如果流已经关闭,则调用此方法无效。”因此,即使不需要它,也最好使用它。另外,我不明白返回 null 响应的注释——当然它不会,如果它抛出异常,它不会返回任何东西?
    • Apache HttpClient 从不ever 返回一个空值或部分初始化的响应对象。这与调用#close 的次数无关,而是在 finally 子句中完全不必要的 null 检查
    • @oleg 并且我给出的代码从来没有假设它会返回一个 null 或部分初始化的响应对象,甚至检查这种情况。我不知道你在说什么?
    • [sigh] 这完全没有必要,因为 HttpResponse 永远不能为空,并且如果出现异常,#execute 方法将终止而不返回响应;-)
    【解决方案3】:

    如果您使用上面的 PoolingHttpClientConnectionManager 过程不起作用,自定义 SSLContext 将被忽略。创建 PoolingHttpClientConnectionManager 时必须在构造函数中传递 socketFactoryRegistry。

    SSLContextBuilder builder = SSLContexts.custom();
    builder.loadTrustMaterial(null, new TrustStrategy() {
        @Override
        public boolean isTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            return true;
        }
    });
    SSLContext sslContext = builder.build();
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            sslContext, new X509HostnameVerifier() {
                @Override
                public void verify(String host, SSLSocket ssl)
                        throws IOException {
                }
    
                @Override
                public void verify(String host, X509Certificate cert)
                        throws SSLException {
                }
    
                @Override
                public void verify(String host, String[] cns,
                        String[] subjectAlts) throws SSLException {
                }
    
                @Override
                public boolean verify(String s, SSLSession sslSession) {
                    return true;
                }
            });
    
    Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
            .<ConnectionSocketFactory> create().register("https", sslsf)
            .build();
    
    PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(
            socketFactoryRegistry);
    CloseableHttpClient httpclient = HttpClients.custom()
            .setConnectionManager(cm).build();
    

    【讨论】:

    • 您可以使用 SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER,而不是构建自己的 X509HostnameVerifier。
    • 正如下面@ri​​ch95 所标记的,HttpClients 的默认设置是为您提供一个 PoolingHttpClient,因此这经常是相关的。在发现我需要这个之前,我必须尝试很多这些答案。
    • 试图在 WebSphere 上应用这个并得到“java.security.KeyStoreException: IBMTrustManager: Problem access trust store java.io.IOException: Invalid keystore format” 为了避免你需要通过 KeyStore trustStore = KeyStore.getInstance (KeyStore.getDefaultType());而不是 null 到 builder.loadTrustMaterial
    • 实际上,使用 HttpClient 4.5,HttpClients.custom().setConnectionManager(cm).build()HttpClients.custom().setSSLSocketFactory(connectionFactory).build() 都可以使用,因此您无需创建 PoolingHttpClientConnectionManager
    • 创建后如何使用 PoolingHttpClientConnectionManager,我的代码正在运行,但我想知道连接池是否有效
    【解决方案4】:

    vasekt 对答案的一个小补充:

    提供的 SocketFactoryRegistry 解决方案在使用 PoolingHttpClientConnectionManager 时有效。

    但是,通过普通 http 的连接不再起作用。您必须另外为 http 协议添加一个 PlainConnectionSocketFactory 才能使它们再次工作:

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

    【讨论】:

    • 我相信http 协议默认使用PlainConnectionSocketFactory 。我只注册了https,而httpclient 仍然可以获得纯HTTP URL。所以我认为这一步没有必要。
    • @soulmachine 它不会用于PoolingHttpClientConnectionManager
    • 谢谢@migo.. 我绝对需要两者,在 qa 我处理 http,在生产中,它是 https
    【解决方案5】:

    (我会直接在 vasekt 的回答中添加评论,但我没有足够的声望点(不确定那里的逻辑)

    无论如何...我想说的是,即使您没有明确创建/请求 PoolingConnection,也不意味着您没有得到一个。

    我疯了,想弄清楚为什么原来的解决方案对我不起作用,但我忽略了 vasekt 的回答,因为它“不适用于我的情况”——错了!

    我在低时盯着我的堆栈跟踪,发现我在它中间看到了一个 PoolingConnection。 Bang - 我厌倦了他的加入和成功! (我们的演示是明天,我快绝望了):-)

    【讨论】:

      【解决方案6】:

      在尝试了各种选项后,以下配置对 http 和 https 都有效:

      SSLContextBuilder builder = new SSLContextBuilder();
      builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
      SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                      builder.build(), SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
      
      Registry<ConnectionSocketFactory> registry = RegistryBuilder. 
                       <ConnectionSocketFactory> create()
                      .register("http", new PlainConnectionSocketFactory())
                      .register("https", sslsf)
                      .build();
      
      PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
      cm.setMaxTotal(2000);
      
      CloseableHttpClient httpClient = HttpClients.custom()
                      .setSSLSocketFactory(sslsf)
                      .setConnectionManager(cm)
                      .build();
      

      我正在使用 http-client 4.3.3:compile 'org.apache.httpcomponents:httpclient:4.3.3'

      【讨论】:

      • 感谢您提供全面、完整的示例!我在以前的解决方案中遇到了多个问题,这非常有帮助。还帮助您提供了导入语句,因为有多个具有相同名称的类,增加了混乱。
      【解决方案7】:
      class ApacheHttpClient {
      
          /***
           * This is a https get request that bypasses certificate checking and hostname verifier.
           * It uses basis authentication method.
           * It is tested with Apache httpclient-4.4.
           * It dumps the contents of a https page on the console output.
           * It is very similar to http get request, but with the additional customization of
           *   - credential provider, and
           *   - SSLConnectionSocketFactory to bypass certification checking and hostname verifier.
           * @param path String
           * @param username String
           * @param password String
           * @throws IOException
           */
          public void get(String path, String username, String password) throws IOException {
              final CloseableHttpClient httpClient = HttpClients.custom()
                      .setDefaultCredentialsProvider(createCredsProvider(username, password))
                      .setSSLSocketFactory(createGenerousSSLSocketFactory())
                      .build();
      
              final CloseableHttpResponse response = httpClient.execute(new HttpGet(path));
              try {
                  HttpEntity entity = response.getEntity();
                  if (entity == null)
                      return;
                  System.out.println(EntityUtils.toString(entity));
              } finally {
                  response.close();
                  httpClient.close();
              }
          }
      
          private CredentialsProvider createCredsProvider(String username, String password) {
              CredentialsProvider credsProvider = new BasicCredentialsProvider();
              credsProvider.setCredentials(
                      AuthScope.ANY,
                      new UsernamePasswordCredentials(username, password));
              return credsProvider;
          }
      
          /***
           * 
           * @return SSLConnectionSocketFactory that bypass certificate check and bypass HostnameVerifier
           */
          private SSLConnectionSocketFactory createGenerousSSLSocketFactory() {
              SSLContext sslContext;
              try {
                  sslContext = SSLContext.getInstance("SSL");
                  sslContext.init(null, new TrustManager[]{createGenerousTrustManager()}, new SecureRandom());
              } catch (KeyManagementException | NoSuchAlgorithmException e) {
                  e.printStackTrace();
                  return null;
              }
              return new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
          }
      
          private X509TrustManager createGenerousTrustManager() {
              return new X509TrustManager() {
                  @Override
                  public void checkClientTrusted(X509Certificate[] cert, String s) throws CertificateException {
                  }
      
                  @Override
                  public void checkServerTrusted(X509Certificate[] cert, String s) throws CertificateException {
                  }
      
                  @Override
                  public X509Certificate[] getAcceptedIssuers() {
                      return null;
                  }
              };
          }
      }
      

      【讨论】:

        【解决方案8】:

        更简单、更短的工作代码:

        我们使用的是 HTTPClient 4.3.5,我们尝试了 stackoverflow 上几乎所有的解决方案,但没有, 经过思考和解决问题后,我们得出以下完美运行的代码, 只需在创建 HttpClient 实例之前添加它。

        你用来发出post请求的一些方法...

        SSLContextBuilder builder = new SSLContextBuilder();
            builder.loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            });
        
            SSLConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(builder.build(),
                    SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        
            HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslSF).build();
            HttpPost postRequest = new HttpPost(url);
        

        继续以正常形式调用和使用 HttpPost 实例

        【讨论】:

        • 我们如何在标题中发布数据?如果我们这样做了,那么请查看 HTTP/1.1 400 Bad Request
        • 适用于 4.5,谢谢! (虽然使用了大量已弃用的东西 LOL)
        【解决方案9】:

        使用 http 客户端 4.5 时,我必须使用 javasx.net.ssl.HostnameVerifier 来允许任何主机名(用于测试目的)。这是我最终做的:

        CloseableHttpClient httpClient = null;
            try {
                SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
                sslContextBuilder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
        
                HostnameVerifier hostnameVerifierAllowAll = new HostnameVerifier() 
                    {
                        public boolean verify(String hostname, SSLSession session) {
                            return true;
                        }
                    };
        
                SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContextBuilder.build(), hostnameVerifierAllowAll);
        
                CredentialsProvider credsProvider = new BasicCredentialsProvider();
                credsProvider.setCredentials(
                    new AuthScope("192.168.30.34", 8443),
                    new UsernamePasswordCredentials("root", "password"));
        
                httpClient = HttpClients.custom()
                    .setSSLSocketFactory(sslSocketFactory)
                    .setDefaultCredentialsProvider(credsProvider)
                    .build();
        
                HttpGet httpGet = new HttpGet("https://192.168.30.34:8443/axis/services/getStuff?firstResult=0&maxResults=1000");
        
                CloseableHttpResponse response = httpClient.execute(httpGet);
        
                int httpStatus = response.getStatusLine().getStatusCode();
                if (httpStatus >= 200 && httpStatus < 300) { [...]
                } else {
                    throw new ClientProtocolException("Unexpected response status: " + httpStatus);
                }
        
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            finally {
                try {
                    httpClient.close();
                } catch (IOException ex) {
                    logger.error("Error while closing the HTTP client: ", ex);
                }
            }
        

        【讨论】:

        • HostnameVerifier 的实现解决了 HTTPClient 4.5 的问题。
        • 喜欢lambdas (JDK1.8)的朋友,可以把SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContextBuilder.build(), hostnameVerifierAllowAll);换成SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContextBuilder.build(), (hostName, sslSession) -&gt; true);。它避免了匿名类并使代码更具可读性。
        【解决方案10】:

        信任 Apache HTTP 客户端中的所有证书

        TrustManager[] trustAllCerts = new TrustManager[]{
                            new X509TrustManager() {
                                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                                    return null;
                                }
                                public void checkClientTrusted(
                                    java.security.cert.X509Certificate[] certs, String authType) {
                                }
                                public void checkServerTrusted(
                                    java.security.cert.X509Certificate[] certs, String authType) {
                                }
                            }
                        };
        
                  try {
                        SSLContext sc = SSLContext.getInstance("SSL");
                        sc.init(null, trustAllCerts, new java.security.SecureRandom());
                        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                                sc);
                        httpclient = HttpClients.custom().setSSLSocketFactory(
                                sslsf).build();
                        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        

        【讨论】:

        • 这适用于 httpclient 4.5.9 ,只需复制并粘贴整个内容即可。
        【解决方案11】:

        PoolingHttpClientConnectionManagerRegistry&lt;ConnectionSocketFactory&gt; socketFactoryRegistry = RegistryBuilder.&lt;ConnectionSocketFactory&gt; create().register("https", sslFactory).build(); 之上 如果你想要一个使用PoolingNHttpClientConnectionManager 的异步httpclient,代码应该类似于以下

        SSLContextBuilder builder = SSLContexts.custom();
        builder.loadTrustMaterial(null, new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] chain, String authType)
                    throws CertificateException {
                return true;
            }
        });
        SSLContext sslContext = builder.build();
        SchemeIOSessionStrategy sslioSessionStrategy = new SSLIOSessionStrategy(sslContext, 
                        new HostnameVerifier(){
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        return true;// TODO as of now allow all hostnames
                    }
                });
        Registry<SchemeIOSessionStrategy> sslioSessionRegistry = RegistryBuilder.<SchemeIOSessionStrategy>create().register("https", sslioSessionStrategy).build();
        PoolingNHttpClientConnectionManager ncm  = new PoolingNHttpClientConnectionManager(new DefaultConnectingIOReactor(),sslioSessionRegistry);
        CloseableHttpAsyncClient asyncHttpClient = HttpAsyncClients.custom().setConnectionManager(ncm).build();
        asyncHttpClient.start();        
        

        【讨论】:

          【解决方案12】:

          这是对上述技术的一个有效提炼,相当于“curl --insecure”:

          HttpClient getInsecureHttpClient() throws GeneralSecurityException {
              TrustStrategy trustStrategy = new TrustStrategy() {
                  @Override
                  public boolean isTrusted(X509Certificate[] chain, String authType) {
                      return true;
                  }
              };
          
              HostnameVerifier hostnameVerifier = new HostnameVerifier() {
                  @Override
                  public boolean verify(String hostname, SSLSession session) {
                      return true;
                  }
              };
          
              return HttpClients.custom()
                      .setSSLSocketFactory(new SSLConnectionSocketFactory(
                              new SSLContextBuilder().loadTrustMaterial(trustStrategy).build(),
                              hostnameVerifier))
                      .build();
          }
          

          【讨论】:

            【解决方案13】:

            您可以使用以下代码 sn-p 获取 HttpClient 实例而无需检查 ssl 认证。

            private HttpClient getSSLHttpClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
            
                    LogLoader.serverLog.trace("In getSSLHttpClient()");
            
                    SSLContext context = SSLContext.getInstance("SSL");
            
                    TrustManager tm = new X509TrustManager() {
                        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        }
            
                        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        }
            
                        public X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }
                    };
            
                    context.init(null, new TrustManager[] { tm }, null);
            
                    HttpClientBuilder builder = HttpClientBuilder.create();
                    SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(context);
                    builder.setSSLSocketFactory(sslConnectionFactory);
            
                    PlainConnectionSocketFactory plainConnectionSocketFactory = new PlainConnectionSocketFactory();
                    Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                            .register("https", sslConnectionFactory).register("http", plainConnectionSocketFactory).build();
            
                    PoolingHttpClientConnectionManager ccm = new PoolingHttpClientConnectionManager(registry);
                    ccm.setMaxTotal(BaseConstant.CONNECTION_POOL_SIZE);
                    ccm.setDefaultMaxPerRoute(BaseConstant.CONNECTION_POOL_SIZE);
                    builder.setConnectionManager((HttpClientConnectionManager) ccm);
            
                    builder.disableRedirectHandling();
            
                    LogLoader.serverLog.trace("Out getSSLHttpClient()");
            
                    return builder.build();
                }
            

            【讨论】:

              【解决方案14】:

              如果您使用的是 HttpClient 4.5.x,您的代码可能类似于以下内容:

              SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null,
                      TrustSelfSignedStrategy.INSTANCE).build();
              SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
                      sslContext, NoopHostnameVerifier.INSTANCE);
              
              HttpClient httpClient = HttpClients.custom()
                                                 .setDefaultCookieStore(new BasicCookieStore())
                                                 .setSSLSocketFactory(sslSocketFactory)
                                                 .build();
              

              【讨论】:

              • 对我不起作用。我正在使用 HttpClient:4.5.5。和 HttpCore 4.4.9
              【解决方案15】:

              对上面@divbyzero 的回答稍作调整,以修复声纳安全​​警告

              CloseableHttpClient getInsecureHttpClient() throws GeneralSecurityException {
                          TrustStrategy trustStrategy = (chain, authType) -> true;
              
                          HostnameVerifier hostnameVerifier = (hostname, session) -> hostname.equalsIgnoreCase(session.getPeerHost());
              
                          return HttpClients.custom()
                                  .setSSLSocketFactory(new SSLConnectionSocketFactory(new SSLContextBuilder().loadTrustMaterial(trustStrategy).build(), hostnameVerifier))
                                  .build();
                      }
              

              【讨论】:

                【解决方案16】:

                最初,我能够使用信任策略禁用 localhost,后来我添加了 NoopH​​ostnameVerifier。现在它将适用于 localhost 和任何机器名称

                SSLContext sslContext = SSLContextBuilder.create().loadTrustMaterial(null, new TrustStrategy() {
                
                            @Override
                            public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                                return true;
                            }
                
                        }).build();
                        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                                sslContext, NoopHostnameVerifier.INSTANCE);
                        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
                

                【讨论】:

                  猜你喜欢
                  • 2011-02-11
                  • 2021-11-21
                  • 2017-02-16
                  • 1970-01-01
                  • 2017-12-17
                  • 2023-03-31
                  • 2016-01-28
                  • 1970-01-01
                  相关资源
                  最近更新 更多