Java 使用证书 请求 Https

需求: 第三方接口请求需要我提供对应证书才能建立起请求,例如 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();
        }

    }
}

上一篇:TCP文件上传实现


下一篇:【Java Socket网络编程】模拟一个客户端和服务端,客户端向服务端传送图片,服务端接收成功后向客户端发送反馈信息