需求: 第三方接口请求需要我提供对应证书才能建立起请求,例如 Apple Pay 接口就需要有对应证书才能请求,找了 很多博客 大部分方法 不是 绕过SSL 就是 代码不全 又或者是 根本就用不了
1、在实现的过程当中,被几个博客给绕晕了。
例如 这段代码
//CA根证书文件路径 private String caPath = "D:\key.jks"; //CA根证书生成密码 private String caPassword = "123456"; //客户端证书文件名 private String clientCertPath = "d:\va.jks"; //客户端证书生成密码 private String clientCertPassword = "123456";
我一直不明白 CA证书文件是哪里生成出来的,因为我目前手上只有一个客户端证书,没有多余的文件了,后来 无意间问了一下 别人 ca根证书 和 Java的cacerts 信任库有什么区别 ,原来博客中说的 ca证书就是jdk下面的 cacerts 证书信任库,路径在 jdk安转目录下的 \jre\lib\security\cacerts, 默认密码是 changeit
客户端证书 就是 第三方给我们的证书, 不一定是 jks文件,可以是 p12、cer、csr文件等
import lombok.extern.slf4j.Slf4j; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.ssl.SSLContexts; import org.junit.Test; import org.linlinjava.litemall.core.util.HttpUtil; import org.springframework.boot.test.context.SpringBootTest; import javax.net.ssl.*; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.HashMap; import java.util.Map; /** * @Author Lizr * @Doc * @CreateTime 2022-01-25 下午 3:58 **/ @Slf4j @SpringBootTest public class HttpTest { // JDK 信任库文件路径 private String caPath = "F:\\JAVA\\jre\\lib\\security\\cacerts"; //CA根证书生成密码 private String caPassword = "changeit"; //客户端证书文件路径 private String clientCertPath = "E:\\key.p12"; //客户端证书密码 private String clientCertPassword = "a123456"; private SSLSocketFactory sslFactory; @Test public void test() throws Exception { // 测试执行 HttpTest test = new HttpTest(); test.httpsPost("https://cn-apple-pay-gateway.apple.com/paymentservices/paymentSession", ""); } //https POST请求返回结果和结果码 /** * @param requestUrl 请求地址 * @param xml JSON字符串参数 */ public Map<String, Object> httpsPost(String requestUrl, String xml) throws Exception { Map<String, Object> map = new HashMap<>(); OutputStreamWriter wr = null; HttpURLConnection conn = null; try { URL url = new URL(requestUrl); //start 这一段代码必须加在open之前,即支持ip访问的关键代码 HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String s, SSLSession sslSession) { return true; } }); //end byte[] xmlBytes = xml.getBytes(); conn = (HttpsURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setInstanceFollowRedirects(true); conn.setRequestMethod("POST"); //根据自己项目需求设置Content-Type conn.setRequestProperty("Content-Type", "application/xml;charset=UTF-8"); conn.setRequestProperty("Content-Length", String.valueOf(xmlBytes.length)); ((HttpsURLConnection) conn).setSSLSocketFactory(getSslFactory()); wr = new OutputStreamWriter(conn.getOutputStream()); wr.write(xml); wr.close(); conn.connect(); String responseBody = getResponseBodyAsString(conn); int responseCode = getResponseCode(conn); map.put("responseBody", responseBody); map.put("responseCode", responseCode); if (getResponseCode(conn) == 200) { System.out.println("请求成功"); } else { System.out.println("请求失败"); } System.out.println(responseBody); conn.disconnect(); } catch (Exception e) { log.error("HTTPS请求出现异常,请求参数为:" + xml); e.printStackTrace(); throw e; } finally { try { if (wr != null) { wr.close(); } if (conn != null) { conn.disconnect(); } } catch (Exception e) { } } return map; } // 创建一个自定义SSLSocketFactory public SSLSocketFactory getSslFactory() throws Exception { if (sslFactory == null) { SSLContext sslContext = SSLContext.getInstance("SSL"); TrustManager[] tm = {new MyX509TrustManager()}; KeyStore trustStore = KeyStore.getInstance("JKS"); //加载客户端证书 FileInputStream clientInputStream = new FileInputStream(clientCertPath); trustStore.load(clientInputStream, clientCertPassword.toCharArray()); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(trustStore, clientCertPassword.toCharArray()); sslContext.init(kmf.getKeyManagers(), tm, new SecureRandom()); sslFactory = sslContext.getSocketFactory(); } return sslFactory; } // 状态码 public int getResponseCode(HttpURLConnection connection) throws Exception { return connection.getResponseCode(); } public String getResponseBodyAsString(HttpURLConnection connection) throws Exception { BufferedReader reader = null; if (connection.getResponseCode() == 200) { reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); } else { reader = new BufferedReader(new InputStreamReader(connection.getErrorStream())); } StringBuffer buffer = new StringBuffer(); String line = null; while ((line = reader.readLine()) != null) { buffer.append(line); } reader.close(); return buffer.toString(); } // 创建证书管理器类 class MyX509TrustManager implements X509TrustManager { private X509TrustManager sunJSSEX509TrustManager; MyX509TrustManager() throws Exception { KeyStore ks = KeyStore.getInstance("JKS"); //获取CA证书 FileInputStream caInputStream = new FileInputStream(caPath); ks.load(caInputStream, caPassword.toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509", "SunJSSE"); tmf.init(ks); TrustManager tms[] = tmf.getTrustManagers(); for (int i = 0; i < tms.length; i++) { if (tms[i] instanceof X509TrustManager) { sunJSSEX509TrustManager = (X509TrustManager) tms[i]; return; } } throw new Exception("Couldn't not initialize"); } @Override public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { try { sunJSSEX509TrustManager.checkClientTrusted(x509Certificates, s); } catch (Exception e) { } } @Override public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { try { sunJSSEX509TrustManager.checkServerTrusted(x509Certificates, s); } catch (Exception e) { } } @Override public X509Certificate[] getAcceptedIssuers() { return sunJSSEX509TrustManager.getAcceptedIssuers(); } } }