HttpClient https Post 请求失败
HttpClient https Post request fails
我正在尝试以下一种方式发出 post 请求:
- 我用的是Apache的HttpClient3.1
- 我使用编码"application/x-www-form-urlencoded"
- 我用的URL开头是https
这是我尝试使用的代码 运行:
public static String httpsPost(String url, String body, String mediaType, String encoding) {
disableCertificateValidation();
HttpClient client = new HttpClient();
StringRequestEntity requestEntity = new StringRequestEntity(body, mediaType, encoding);
PostMethod method = new PostMethod(url);
method.setRequestEntity(requestEntity);
client.executeMethod(method);
}
public static void disableCertificateValidation() {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
}};
// Ignore differences between given hostname and certificate hostname
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) { return true; }
};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(hv);
} catch (Exception e) {}
}
在执行 executeMethod
时我发现:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
我试过 disable certificate validation 但没用。
如果您想完全忽略证书,请查看此处的答案Ignore self-signed ssl cert using Jersey Client
尽管这会使您的应用容易受到中间人攻击。
您可以尝试将证书作为可信证书添加到您的 java 存储中,而不是这样做。这个网站可能会有帮助。 http://blog.icodejava.com/tag/get-public-key-of-ssl-certificate-in-java/
这是显示如何向您的商店添加证书的另一个答案。 Java SSL connect, add server cert to keystore programatically
关键是
KeyStore.Entry newEntry = new KeyStore.TrustedCertificateEntry(someCert);
ks.setEntry("someAlias", newEntry, null);`
我重构了旧代码以处理 https。现在它可以工作了,看起来像这样:
public static String httpsPost(String url, String body, String mediaType, String encoding) {
SSLContext ctx;
ctx = SSLContext.getInstance("TLS");
ctx.init(new KeyManager[0], new TrustManager[]{new DefaultTrustManager()}, new SecureRandom());
SSLContext.setDefault(ctx);
HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
URL serverUrl = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) serverUrl.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
con.connect();
OutputStreamWriter post = new OutputStreamWriter(con.getOutputStream());
post.write(body);
post.flush();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
String content = "";
while ((inputLine = in.readLine()) != null) {
content += inputLine;
}
post.close();
in.close();
return content;
}
我正在尝试以下一种方式发出 post 请求:
- 我用的是Apache的HttpClient3.1
- 我使用编码"application/x-www-form-urlencoded"
- 我用的URL开头是https
这是我尝试使用的代码 运行:
public static String httpsPost(String url, String body, String mediaType, String encoding) {
disableCertificateValidation();
HttpClient client = new HttpClient();
StringRequestEntity requestEntity = new StringRequestEntity(body, mediaType, encoding);
PostMethod method = new PostMethod(url);
method.setRequestEntity(requestEntity);
client.executeMethod(method);
}
public static void disableCertificateValidation() {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
}};
// Ignore differences between given hostname and certificate hostname
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) { return true; }
};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(hv);
} catch (Exception e) {}
}
在执行 executeMethod
时我发现:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
我试过 disable certificate validation 但没用。
如果您想完全忽略证书,请查看此处的答案Ignore self-signed ssl cert using Jersey Client
尽管这会使您的应用容易受到中间人攻击。
您可以尝试将证书作为可信证书添加到您的 java 存储中,而不是这样做。这个网站可能会有帮助。 http://blog.icodejava.com/tag/get-public-key-of-ssl-certificate-in-java/
这是显示如何向您的商店添加证书的另一个答案。 Java SSL connect, add server cert to keystore programatically
关键是
KeyStore.Entry newEntry = new KeyStore.TrustedCertificateEntry(someCert);
ks.setEntry("someAlias", newEntry, null);`
我重构了旧代码以处理 https。现在它可以工作了,看起来像这样:
public static String httpsPost(String url, String body, String mediaType, String encoding) {
SSLContext ctx;
ctx = SSLContext.getInstance("TLS");
ctx.init(new KeyManager[0], new TrustManager[]{new DefaultTrustManager()}, new SecureRandom());
SSLContext.setDefault(ctx);
HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
URL serverUrl = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) serverUrl.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
con.connect();
OutputStreamWriter post = new OutputStreamWriter(con.getOutputStream());
post.write(body);
post.flush();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
String content = "";
while ((inputLine = in.readLine()) != null) {
content += inputLine;
}
post.close();
in.close();
return content;
}