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

2022-08-09 14:51:49 浏览数 (1)

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

简单说下: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 = "rn";
    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

0 人点赞