Java get/post的https请求忽略ssl证书认证
需求
最近在负责一个对接第三方服务的事情,在对接期间,因为第三方服务为https的请求,众所周知,请求https请求会使用本地的证书公钥去访问服务SSL证书,应我本地并没有对应的SSL证书,所以请求不到服务,请求接口时报如下错误。翻阅资源发现是可以 忽略SSL认证的。
- unable to find valid certification path to requested target
工具类
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class SslUtils {
private static void trustAllHttpsCertificates() throws Exception {
TrustManager[] trustAllCerts = new TrustManager[1];
TrustManager tm = new miTM();
trustAllCerts[0] = tm;
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
static class miTM implements TrustManager, X509TrustManager {
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(X509Certificate[] certs) {
return true;
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
return;
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
return;
}
}
/**
* 忽略HTTPS请求的SSL证书,必须在openConnection之前调用
*
* @throws Exception
*/
public static void ignoreSsl() throws Exception {
HostnameVerifier hv = new HostnameVerifier() {
@Override
public boolean verify(String urlHostName, SSLSession session) {
System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
return true;
}
};
trustAllHttpsCertificates();
HttpsURLConnection.setDefaultHostnameVerifier(hv);
}
/**
* 避免HttpClient的”SSLPeerUnverifiedException: peer not authenticated”异常
* * 不用导入SSL证书 * * @param base * @return */ public static HttpClient wrapClient(HttpClient base) { try { SSLContext ctx = SSLContext.getInstance("TLS"); X509TrustManager tm = new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} @Override public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} }; ctx.init(null, new TrustManager[]{tm}, null); SSLConnectionSocketFactory ssf = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE); CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(ssf).build(); return httpclient; } catch (Exception ex) { ex.printStackTrace(); return HttpClients.createDefault(); } } /** * 跳过证书效验的sslcontext * * @return * @throws Exception */ private static SSLContext createIgnoreVerifySSL() throws Exception { SSLContext sc = SSLContext.getInstance("TLS"); // 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法 X509TrustManager trustManager = new X509TrustManager() { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException { } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } }; sc.init(null, new TrustManager[] { trustManager }, null); return sc; } /** * 构造RestTemplate * * @return * @throws Exception */ public static RestTemplate getRestTemplate() throws Exception { HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); // 超时// factory.setConnectionRequestTimeout(5000);// factory.setConnectTimeout(5000);// factory.setReadTimeout(5000); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(createIgnoreVerifySSL(), // 指定TLS版本 null, // 指定算法 null, // 取消域名验证 new HostnameVerifier() { @Override public boolean verify(String string, SSLSession ssls) { return true; } }); CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); factory.setHttpClient(httpClient); RestTemplate restTemplate = new RestTemplate(factory); // 解决中文乱码问题 restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8)); return restTemplate; }}
使用方法
@Override
public void completionIndexPushToODS(List data) throws Exception {
try {
//请求地址
String url ="https://.....";
//请求参数
String requestData = JSON.toJSONString(data);
System.out.println("请求参数:" + requestData);
RestTemplate restTemplate;
if (flag) {
//HTTP绕过SSL证书认证
restTemplate = SslUtils.getRestTemplate();
} else {
//普通请求方式
restTemplate = new RestTemplate();
}
//自定义header传输信息(根据自己的需求设置)
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
HttpEntity<MultiValueMap> httpEntity = new HttpEntity(JSON.toJSON(data), httpHeaders);
URI uri = new URI(url);
System.out.println("开始请求");
//POST返回字节方式
byte[] response = restTemplate.postForObject(uri, httpEntity, byte[].class);
//GET请求返回字符
//String request = restTemplate.getForObject(uri, String.class);
System.out.println("请求结束");
if (response == null) {
System.out.println("返回值为空");
}
String result = new String(response, "utf-8");
System.out.println("返回结果:" + result);
} catch (Exception e) {
e.printStackTrace();
}
}
本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://www.net2asp.com/f250400e37.html
