Apache Http客户端。您可以看到相关代码here:
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证书错误的方法(只设置为暂存,它不会在生产中使用)。但是,我仍然得到以下异常/ stacktrace:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building unable to find valid certification path to requested target
任何提示都会很棒。如果我在做TrustManager错误,或者我应该以不同方式执行HTTP Post方法。
谢谢!
答案 0 :(得分:12)
首先,不要忽略证书错误。相反,处理他们。忽略证书错误会打开与潜在MITM攻击的连接。这就像关闭烟雾报警器中的蜂鸣器一样,因为有时会发出噪音......
当然,很有可能说它只适用于测试代码,它不会最终投入生产,但我们都知道在截止日期临近时会发生什么:代码在测试时没有显示任何错误 - >我们可以按原样发货。如果需要,您应该设置测试CA.这并不是很难,而且整个过程肯定不比引入自定义开发代码和在生产中删除它更难。
你明显使用Apache Http Client:
HttpClient client = new HttpClient();
int statusCode = client.executeMethod(method);
然而,您正在使用您创建的javax.net.ssl.HttpsURLConnection
初始化SSLContext
:
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
这完全独立于Apache Http客户端设置。
相反,您应该为Apache Http客户端库设置SSLContext
,如this answer中所述。如果您使用的是Apache Http Client 3.x,则需要设置自己的SecureProtocolSocketFactory
以使用SSLContext
(请参阅示例here)。值得升级到Apache Http Client 4.x,它直接支持SSLContext
。
您还可以使用Pascal's answer正确导入证书。同样,如果您按照接受的答案(凯文)来解决该问题,您确实会忽略该错误,但这会使连接容易受到MITM攻击。
答案 1 :(得分:1)
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();
应该解决你的问题
答案 2 :(得分:1)
如果你真的想忽略这对我有用的一切:
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()
答案 3 :(得分:0)
忽略证书会对其造成伤害,因为相同的代码可能会在生产环境中移动,并可能造成严重破坏。
以下示例是 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;
}