基于springboot 根据ca.crt、client.crt和client.key文件实现与服务端https通讯

基于springboot 根据ca.crt、client.crt和client.key文件实现与服务端https通讯

服务端提供了三个文件需要进行TLS方式通讯,三个文件分别为ca.crt、client.crt、client.key:
ca.crt 为服务端证书
client.crt 为服务端分配给客户端的证书
client.key 为服务端分配给客户端证书私钥

三个文件的具体格式说明我就不做赘述了,都可以在网上查到,也不多说废话,直接贴代码:

参考文章

参考文章: https://blog.csdn.net/qq_38417913/article/details/82150186.

pom.xml添加依赖

// pom.xml 添加依赖
<dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpclient</artifactId>
      <version>4.5.6</version>
    </dependency>

客户端认证代码

// An highlighted block


import com.alibaba.fastjson.JSONObject;
import com.Exception.base.exceptions.BusinessException;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import sun.misc.BASE64Decoder;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;


/**
 * @ClassName CertificateHttpsTools
 * @Description 客户端带证书https方式请求服务端
 * @Author user
 * @Date 2020/6/18 10:23
 * @Version 1.0
 **/
@Component
public class CertificateHttpsTools {
    private static Logger logger = LogManager.getLogger(CertificateHttpsTools.class);


    public static final String CA_PATH = "C:/Users/Desktop/cer/ca.crt";
    public static final String CRT_PATH = "C:/Users/Desktop/cer/client.crt";
    public static final String KEY_PATH = "C:/Users/Desktop/cer/client.key";
    public static final String PASSWORD = "123";

    public static String httpPost(String url,  String jsonParam) throws IOException {
        CloseableHttpClient httpClient = null;

        String result = null;
        logger.info("请求数据:"+jsonParam);

        try{
            //加载证书
            SSLConnectionSocketFactory sslsf = getSSLSocktetBidirectional();
            //设置认证信息到httpclient
            httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

        }catch (Exception e){
            logger.error("证书读取失败");
            e.printStackTrace();
            throw new BusinessException("证书读取失败");


        }

        // 根据默认超时限制初始化requestConfig
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(25000).setConnectTimeout(25000).build();

        //post通讯初始化
        HttpPost httpPost = new HttpPost(url);

        // 设置报文头  得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
        httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

        //添加请求报文体
        StringEntity reqentity = new StringEntity(jsonParam,  "UTF-8");
        httpPost.setEntity(reqentity);

        // 设置请求器的配置
        httpPost.setConfig(requestConfig);


        try {
            CloseableHttpResponse response = null;
            InputStream reqin = null;
            try {

                //打印请求报文体
                reqin = httpPost.getEntity().getContent();
                String reqBbody = StreamUtils.copyToString(reqin, StandardCharsets.UTF_8);
                logger.info("请求数据:"+reqBbody);

                //与服务端通讯
                response = httpClient.execute(httpPost);

                //打印通讯状态
                logger.info(JSONObject.toJSONString(response.getStatusLine()));

                HttpEntity entity = response.getEntity();
                InputStream in = null;
                try {

                    in = entity.getContent();
                    String rspBbody = StreamUtils.copyToString(in, StandardCharsets.UTF_8);
                    logger.info("应答为:"+rspBbody);
                    in.close();

                    result = rspBbody;

//                result = EntityUtils.toString(entity, "UTF-8");


                } catch (IOException e) {
                    logger.error("服务端应答信息读取失败");
                    e.printStackTrace();
                    throw new BusinessException("服务端应答信息读取失败");
                }finally {
                    if (in !=null){
                        in.close();
                    }
                }

            } catch (IOException e) {
                logger.error("与服务端通讯失败");
                e.printStackTrace();
                throw new BusinessException("与服务端通讯失败");
            }finally {
                try{
                    //释放资源
                    if (httpClient != null){
                        httpClient.close();
                    }

                    if (response != null){
                        response.close();
                    }
                    if (reqin != null){
                        reqin.close();
                    }
                }catch (IOException e) {
                    e.printStackTrace();
                }
            }


        } finally {

            httpPost.abort();

        }
        return result;

    }

       public static SSLConnectionSocketFactory getSSLSocktetBidirectional() throws Exception {
        SSLConnectionSocketFactory sslsf = null;

        try{
            // CA certificate is used to authenticate server
            CertificateFactory cAf = CertificateFactory.getInstance("X.509");
            FileInputStream caIn = new FileInputStream(CA_PATH);
            X509Certificate ca = (X509Certificate) cAf.generateCertificate(caIn);

            KeyStore caKs = KeyStore.getInstance("JKS");
            caKs.load(null, null);
            caKs.setCertificateEntry("ca-certificate", ca);
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
            tmf.init(caKs);

            // client key and certificates are sent to server so it can authenticate us
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            FileInputStream crtIn = new FileInputStream(CRT_PATH);
            X509Certificate caCert = (X509Certificate) cf.generateCertificate(crtIn);
            crtIn.close();


            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
            ks.load(null, null);
            ks.setCertificateEntry("certificate", caCert);
            ks.setKeyEntry("private-key", getPrivateKey( KEY_PATH), PASSWORD.toCharArray(), new java.security.cert.Certificate[] { caCert });
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX");
            kmf.init(ks, PASSWORD.toCharArray());

            // finally, create SSL socket factory
            SSLContext context = SSLContext.getInstance("TLSv1.2");
            context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());

            sslsf =
                    new SSLConnectionSocketFactory(context,null, null,
                            NoopHostnameVerifier.INSTANCE);
        }catch (Exception e){
            logger.error("证书加载失败");
            e.printStackTrace();
            throw new BusinessException("证书加载失败");
        }

        return sslsf;
    }


    private static PrivateKey getPrivateKey(String path) throws Exception {
        //byte[] buffer = Base64.getDecoder().decode(getPem(path));
//        Base64 base64 = new Base64();
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] buffer = decoder.decodeBuffer(getPem(path));

        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
        KeyFactory keyFactory = KeyFactory.getInstance("EC");
        return keyFactory.generatePrivate(keySpec);

    }


    private static  String getPem(String path) throws Exception {
        FileInputStream fin = new FileInputStream(path);
        BufferedReader br = new BufferedReader(new InputStreamReader(fin));
        String readLine = null;
        StringBuilder sb = new StringBuilder();
        while ((readLine = br.readLine()) != null) {
            if (readLine.charAt(0) == '-') {
                continue;
            } else {
                sb.append(readLine);
                sb.append('\r');
            }
        }
        fin.close();
        return sb.toString();
    }
}


以上代码亲测有效,如果不对之处请各位大神指正,当然有更好的方法也请各位提出来

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习是不可能停的

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值