大家好,又见面了,我是你们的朋友全栈君。
简单说下: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