前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JAVA https双向验证案例,和生成keyStore文件的方法,https单向认证博文参考地址

JAVA https双向验证案例,和生成keyStore文件的方法,https单向认证博文参考地址

作者头像
全栈程序员站长
发布2022-08-09 14:51:49
1.1K0
发布2022-08-09 14:51:49
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

简单说下:https=http+ssl。因此在代码中就是在http的基础 上先初始化ssl证书的所有信息,二者事由很明显的界限的,在代码中都有讲解。

先解释下keyStore和trutsStore是什么:通信双方分别拥有一个keystore和一个truststore,keystore用于存放自己的密钥和公钥,truststore用于存放所有需要信任方的公钥。

下面两篇博文对https的讲解十分透彻,可参考(感谢两篇文章的博主)

Java-JSSE-SSL/TLS编程代码实例-单向认证

Java-JSSE-SSL/TLS编程代码实例-双向认证

测试类:其中存在一些小编实际代码中需要自定义类,读者可忽略(重点注意红色字体部分)

代码语言:javascript
复制
/**
 * 
 * @author liuxin
 * @date   2018年5月31日
 */
public class TestXiaoYing {

	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
	
		HttpConnector httpConnector = new HttpConnector();
		httpConnector.keyStorePassword="open";
		httpConnector.keyStorePath="D://xiaoying/client095.p12";
		httpConnector.trustStorePassword="kLStEz";
		httpConnector.trustStorePath="D://xiaoying/server.keystore";
		String url="https://hahah";
		//初始化加载证书等
        httpConnector.init();//1,这里是重点,也就是初始化证书,方法跳转到下面一个类的方法
        NoticeBodyRequest body=new NoticeBodyRequest();
        body.setNoticeKeyType("2");
        body.setNoticeKeyValue("20170526220000000044");
        body.setNoticeType("2");
        body.setResultCode("22");
        body.setResultDesc("ww");
        
        NoticeRequest req=new NoticeRequest();
        req.setChannelId(1);
        req.setNoticeMsg(body);
        req.setNoticeType(1);
        JsonObjectMapper jsonObjectMapper = new JsonObjectMapper();
        String request=jsonObjectMapper.writeValueAsString(req);
        System.out.println(request);
        String res=httpConnector.deal(url,"POST",request);//4,组转好入参后,调用deal方法发送请求,进入到下面一个类中
        System.out.println(res);

	}

}
代码语言:javascript
复制
public class HttpConnector {
	
	Logger logger = LoggerFactory.getLogger(getClass());
	
    public int connectTimeout = 30000;
    public int readTimeout = 10000;
    public String channel = "Test";
    public boolean isSSL = true;
    public String keyStorePath;
    public String keyStorePassword;
    public String trustStorePath;
    public String trustStorePassword;
    public String url="";

    private HttpClient httpClient;

    public void init() throws Exception {
        httpClient = new HttpClient();
        httpClient.config.connectTimeout = connectTimeout;
        httpClient.config.readTimeout = readTimeout;
        httpClient.httpConfig.userAgent = "TrustSign FEP";
        httpClient.httpConfig.contentType = MIMEType.FORM;
        httpClient.httpConfig.accept = MIMEType.JSON;
        try {
            if (isSSL) {
  
  //2,执行初始化方法,跳转到下面类的方法
                httpClient.initSSL(keyStorePath, keyStorePassword.toCharArray(), trustStorePath, trustStorePassword.toCharArray());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String deal(String uri, String method, String request) {
        HttpURLConnection connection = null;
        try {
            connection = httpClient.connect(uri, method);//5,调用connect方法,建立通讯连接
            logger.info("------请求url:"+uri);
            int responseCode = httpClient.send(connection, request == null ? null : CommonUtil.getBytes(request));
            System.out.println("responseCode:" + responseCode);
            return CommonUtil.getString(httpClient.receive(connection));
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        } finally {
            httpClient.disconnect(connection);
        }
    }
代码语言:javascript
复制
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.SecureRandom;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;



public class HttpClient{
	public static final String BOUNDARY = java.util.UUID.randomUUID().toString();
    public static final String PREFIX = "--", LINEND = "\r\n";
    public static final String DEFAULT_CHARSET = "UTF-8";

    public static final int DEFAULT_BUFFER_SIZE = 2048;
    public static final int DEFAULT_CONNECT_TIMEOUT = 3000;
    public static final int DEFAULT_READ_TIMEOUT = 30000;

    public static final String DEFAULT_SSL_PROTOCOL = "TLS";
    public static final String DEFAULT_KEY_ALGORITHM = KeyManagerFactory.getDefaultAlgorithm();
    public static final String DEFAULT_KEY_STORE_TYPE = KeyStore.getDefaultType();
    public static final String DEFAULT_TRUST_ALGORITHM = TrustManagerFactory.getDefaultAlgorithm();
    public static final String DEFAULT_TRUST_STORE_TYPE = KeyStore.getDefaultType();

    public static final String DEFAULT_HTTP_USER_AGENT = "client";
    public static final String DEFAULT_HTTP_CONNECTION = "close";
    public static final String DEFAULT_HTTP_CONTENT_TYPE = "text/plain";
    public static final String DEFAULT_HTTP_ACCEPT = "text/plain";

    class OpenSDKHostNameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            if (hostname.equals("api.hongyi.com")) {
                return true;
            }
            return false;
        }
    }

    public Config config = new Config();
    public SSLConfig sslConfig = new SSLConfig();
    public HttpConfig httpConfig = new HttpConfig();

    private SSLSocketFactory sslSocketFactory;
    //3,ssl证书初始化方法实现类,下面有重点解释
    public void initSSL(String keyStorePath, char[] keyStorePassword, String trustStorePath, char[] trustStorePassword) throws GeneralSecurityException,
            IOException {
    	/**
    	 * https客户端双向认证步骤
    	 * 
    	 * KeyStore类型有如下三种: 
			jceks - The proprietary keystore implementation provided by the SunJCE provider. 
			jks - The proprietary keystore implementation provided by the SUN provider. 
			pkcs12 - The transfer syntax for personal identity information as defined in PKCS #12.
    	 */
    	
    	//1
    	 KeyStore keyStore = KeyStore.getInstance("pkcs12"); //指定keyStore的算法类型
         InputStream inputStream = new FileInputStream(keyStorePath);
         keyStore.load(inputStream, keyStorePassword);//加载server的keyStore文件,并指定keyStore的密码keyStorePass
        
         //2
         KeyStore trustedStore = KeyStore.getInstance("JKS");//指定trustStore的算法类型
         InputStream inputStream1 = new FileInputStream(trustStorePath);
         trustedStore.load(inputStream1, trustStorePassword);//加载server的trustStore文件,并指定trustStore的密码trustStorePass


         //3
         KeyManagerFactory keyManagerFactory = null;//创建KeyManagerFactory对象
         keyManagerFactory = KeyManagerFactory.getInstance("SunX509");//指定keyManagerFactory的算法类型
         keyManagerFactory.init(keyStore, keyStorePassword);//加载1中的keyStore和server的密钥对密码keyStorePass来初始化
        
         //4
         TrustManagerFactory trustManagerFactory = null; //创建trustManagerFactory对象       
         trustManagerFactory = TrustManagerFactory.getInstance("SunX509");//指定TrustManagerFactory的算法类型
         trustManagerFactory.init(trustedStore);//加载2中的trustStore来初始化,trustStore存的是client的公钥,不需要keyPass也能访问。
         
         //5
         SSLContext sslContext = SSLContext.getInstance("TLS");//创建sslContext,并指定SSLContext的算法类型
         //加载3,4中的keymanagerFactory和trustManagerFactory对象来初始化
         sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
         sslSocketFactory = sslContext.getSocketFactory();//创建sslSocketFactory
         //至此,对ssl安全证书的双向验证的所有操作都完成了。同时,可以看出上面的所有操作都是为了得出sslSocketFactory
    }
  //6,connect实现方法,把初始化好的ssl配置加入到http中,让http变成https,至此下面的步骤可以看做http通讯的操作了
    public HttpURLConnection connect(String url, String method) throws MalformedURLException, IOException {
        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
        //6
        if (sslSocketFactory != null) {//承接上面的init()初始化方法,如果sslSocketFactory为null说明没有ssl证书验证,那么就可以看做http通讯了
            HttpsURLConnection httpsConn = (HttpsURLConnection) connection;//把httpURLConnection强转为HTTPsURLConnection
            httpsConn.setSSLSocketFactory(sslSocketFactory);
            if (sslConfig.ignoreHostname) {
                httpsConn.setHostnameVerifier(new OpenSDKHostNameVerifier());
            }
        }
        connection.setConnectTimeout(config.connectTimeout);
        connection.setReadTimeout(config.readTimeout);
        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setUseCaches(false);
        connection.setRequestMethod(method);
        connection.setRequestProperty("User-Agent", "Test Example");
        connection.setRequestProperty("Connection", httpConfig.connection);
        connection.setRequestProperty("Content-Type", httpConfig.contentType + ";charset=" + config.charset);
        connection.setRequestProperty("Accept", httpConfig.accept);
        connection.setRequestProperty("Accept-Charset", config.charset);
        // NOT connect, delay until send() for set length
        return connection;
    }

    public int send(HttpURLConnection connection, byte[] requestData) throws IOException {
        if (requestData != null) {
            connection.setFixedLengthStreamingMode(requestData.length);
            connection.connect();
            OutputStream outputStream = connection.getOutputStream();
            outputStream.write(requestData);
            outputStream.flush();
        } else {
            connection.connect();
        }
        return connection.getResponseCode();
    }



    public byte[] receive(HttpURLConnection connection) throws IOException {
        InputStream inputStream = connection.getErrorStream();
        if (inputStream == null) {
            inputStream = connection.getInputStream();
        }
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(config.bufferSize);
        byte[] buffer = new byte[config.bufferSize];
        int read = -1;
        int length = 0;
        while ((read = inputStream.read(buffer)) != -1) {
            byteArrayOutputStream.write(buffer, 0, read);
            length += read;
        }
        System.out.println("length:" + length);
        return byteArrayOutputStream.toByteArray();
    }

    public void disconnect(HttpURLConnection connection) {
        connection.disconnect();
    }

    public static class Config {
        public String charset = DEFAULT_CHARSET;
        public int bufferSize = DEFAULT_BUFFER_SIZE;
        public int connectTimeout = DEFAULT_CONNECT_TIMEOUT;
        public int readTimeout = DEFAULT_READ_TIMEOUT;
    }

    public static class SSLConfig {
        public String sslProvider = null;
        public String sslProtocol = DEFAULT_SSL_PROTOCOL;
        public String keyProvider = null;
        public String keyAlgorithm = DEFAULT_KEY_ALGORITHM;
        public String keyStoreType = DEFAULT_KEY_STORE_TYPE;
        public String trustProvider = null;
        public String trustAlgorithm = DEFAULT_TRUST_ALGORITHM;
        public String trustStoreType = DEFAULT_TRUST_STORE_TYPE;
        public boolean ignoreHostname = true;
    }

    public static class HttpConfig {
        public String userAgent = DEFAULT_HTTP_USER_AGENT;
        public String connection = DEFAULT_HTTP_CONNECTION;
        public String contentType = DEFAULT_HTTP_CONTENT_TYPE;
        public String accept = DEFAULT_HTTP_ACCEPT;
    }
}

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/106097.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年4月2,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
SSL 证书
腾讯云 SSL 证书(SSL Certificates)为您提供 SSL 证书的申请、管理、部署等服务,为您提供一站式 HTTPS 解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档