一、所以HTTPS是HTTP+SSL/TCP的简称。
SSL:(Secure Socket Layer,安全套接字层),位于可靠的面向连接的网络层协议和应用层协议之间的一种协议层。SSL通过互相认证、使用数字签名确保完整性、使用加密确保私密性,以实现客户端和服务器之间的安全通讯。该协议由两层组成:SSL记录协议和SSL握手协议。
TLS:(Transport Layer Security,传输层安全协议),用于两个应用程序之间提供保密性和数据完整性。该协议由两层组成:TLS记录协议和TLS握手协议。
通信双方分别拥有一个keystore和一个truststore,keystore用于存放自己的密钥和公钥,truststore用于存放所有需要信任方的公钥
个人认为:
在保证接口正确的情况下,服务端安装了服务端证书;客户端只需安装客户端证书后,即可进行安全访问。<--不过对于证书访问,在一定程度上是安全的,但会拖慢访问速度-->
二、认证模式
单向认证: 指的是只有一个对象校验对端的证书合法性
(1)通常是客户端来校验服务器的合法性。那么 client 需要一个 ca.crt, 服务器需要 server.crt, server.key
例如:浏览器校验各个 HTTPS 网站的合法性。如果导航栏有绿色的小锁,说明网站合法;如果是红色小锁,说明该网站证书校验不过。
(2)也可以是服务器来校验客户端的合法性。那么 server 需要一个 ca.crt, 客户端需要 client.crt, client.key
例如: 亚马逊物联网平台(AWS IoT) 给每个设备颁发证书,所有设备要想连接上 AWS, 必须使用其提供的客户端证书
单向认证,认证流程
双向认证:指的是相互校验,服务器需要校验每个 client 证书, client 也需要校验服务器证书
server 需要 server.key 、server.crt 、ca.crt
client 需要 client.key 、client.crt 、ca.crt
个人理解:
服务端携带证书请求服务端,服务端在验证客户端证书的时候、客户端也在认证服务端证书;其一认证不通过则终止握手环节,认证成功则加密传输的数据,完成数据访问传输。(彼此相互认证)
不认证:指的是不相互校验证书,但仍然使用 TLS 连接,证书校验只是 TLS 连接过程中的一小步
三、证书生成,可参考
https://zhuanlan.zhihu.com/p/100736598
四、双向测试验证demo
测试代码:
private OkHttpClient getHttpClient(String trustStorePemStr, String trustPassword, String keyStorePemStr, String keyPassword) {
try{
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream keyStoreStream = new FileInputStream(new File(keyStorePemStr));
keyStore.load(keyStoreStream, keyPassword.toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keyPassword.toCharArray());
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
KeyStore trustStore = KeyStore.getInstance("PKCS12");
FileInputStream trustStoreStream = new FileInputStream(new File(trustStorePemStr));
trustStore.load(trustStoreStream, trustPassword.toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
//设置服务端支持的协议
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagers, trustManagers, new SecureRandom());
SSLSocketFactory sslFactory = context.getSocketFactory();
OkHttpClient client = new OkHttpClient.Builder().sslSocketFactory(sslFactory, trustManager).hostnameVerifier((s, sslSession) -> true).build();
return client;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
单例测试
@Test
public void sslTest(){
String requestPath = "https://xxxx:18443/tooan/rest/pda/ticket/endSite";
OkHttpClient client = null;
try {
//root.p12是服务端证书,user.p12是客户端证书,后各自接密码
client = getHttpClient("E:/user.p12","123456","E:/root.p12","123456");//绝对路径
okhttp3.Request request = new okhttp3.Request.Builder().get().url(requestPath).build();
okhttp3.Response response = client.newCall(request).execute();
System.out.println("get返回状态:" + response.code());
System.out.println("get返回结果:" + response.body().string());
response.close();
} catch (Exception e) {
e.printStackTrace();
}
}
测试效果
浏览器访问
注意:引入的架包如下
import javax.net.ssl.*;
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.8.1</version>
</dependency>