使用Java忽略SSL证书错误

Apache Http客户端。 您可以在此处查看相关代码:

String url = "https://path/to/url/service"; HttpClient client = new HttpClient(); PostMethod method = new PostMethod(url); // Test whether to ignore cert errors if (ignoreCertErrors){ TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager(){ public X509Certificate[] getAcceptedIssuers(){ return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) {} public void checkServerTrusted(X509Certificate[] certs, String authType) {} } }; try { SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustAllCerts, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); } catch (Exception e){ e.printStackTrace(); } } try { // Execute the method (Post) and set the results to the responseBodyAsString() int statusCode = client.executeMethod(method); resultsBody = method.getResponseBodyAsString(); } catch (HttpException e){ e.printStackTrace(); } catch (IOException e){ e.printStackTrace(); } finally { method.releaseConnection(); } 

这是每个人都说用来忽略SSL证书错误的方法(仅将其设置为暂存,不会在生产中使用)。 但是,我仍然得到以下exception/ stacktrace:

 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building unable to find valid certification path to requested target 

任何提示都会很棒。 如果我在做TrustManager错误,或者我应该以不同方式执行HTTP Post方法。

谢谢!

首先,不要忽略证书错误。 相反,处理他们。 忽略证书错误会打开与潜在MITM攻击的连接。 这就像关闭烟雾报警器中的蜂鸣器一样,因为有时会发出噪音……

当然,很有可能说它只适用于测试代码,它不会最终投入生产,但我们都知道在截止日期临近时会发生什么:代码在测试时没有显示任何错误 – >我们可以发货原样。 如果需要,您应该设置测试CA. 这并不是很难做到,整个过程肯定不比引入自定义开发代码和在生产中删除它更难。

你明显使用Apache Http Client:

 HttpClient client = new HttpClient(); int statusCode = client.executeMethod(method); 

然而,您正在使用您创建的SSLContext初始化javax.net.ssl.HttpsURLConnection

 HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); 

这完全独立于Apache Http Client设置。

相反,您应该为Apache Http客户端库设置SSLContext ,如本答案中所述 。 如果您正在使用Apache Http Client 3.x,则需要设置自己的SecureProtocolSocketFactory以使用该SSLContext (请参阅此处的示例)。 值得升级到Apache Http Client 4.x,它直接支持SSLContext

您还可以使用Pascal的答案正确导入证书。 同样,如果您按照接受的答案(凯文)来回答这个问题,您确实会忽略错误,但这会使连接容易受到MITM攻击。

HttpClient 4.3,很简单,

  HttpClientBuilder cb = HttpClientBuilder.create(); SSLContextBuilder sslcb = new SSLContextBuilder(); sslcb.loadTrustMaterial(KeyStore.getInstance(KeyStore.getDefaultType()), new TrustSelfSignedStrategy()); cb.setSslcontext(sslcb.build()); CloseableHttpClient httpclient = cb.build(); 

那应该解决你的问题

忽略证书本身就有害,因为相同的代码可以在生产环境中移动,并且可能造成严重破坏。

以下示例是Jersey Rest Client

 private static final com.sun.jersey.api.client.Client client = com.sun.jersey.api.client.Client.create(configureClient()); final com.sun.jersey.api.client.WebResource webResource = client.resource("url"); try { com.sun.jersey.api.client.ClientResponse response = webResource.type(MediaType.APPLICATION_JSON_TYPE) .accept(MediaType.APPLICATION_JSON_TYPE) .get(com.sun.jersey.api.client.ClientResponse.class); }catch(com.sun.jersey.api.client.ClientHandlerException che){ che.printStackTrace(); } 

忽略证书可以如下:

 public static ClientConfig configureClient() { TrustManager[ ] certs = new TrustManager[ ] { new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {} public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {} } }; SSLContext ctx = null; try { ctx = SSLContext.getInstance("SSL"); ctx.init(null, certs, new SecureRandom()); } catch (java.security.GeneralSecurityException ex) { } HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory()); ClientConfig config = new DefaultClientConfig(); try { config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties( new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }, ctx )); } catch(Exception e) { } return config; } 

如果你真的想忽略这对我有用的一切:

 SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(new TrustStrategy() { @Override public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { return true; } }).build(); HostnameVerifier hnv = new NoopHostnameVerifier(); SSLConnectionSocketFactory sslcf = new SSLConnectionSocketFactory(sslContext, hnv); CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslcf).build()