HTTPS即基于SSL的HTTP协议,简单地说就是HTTP的安全版。依托SSL协议,HTTPS协议能够确保整个通信过程都是经过加密的,秘钥是随机产生,并且能够通过数字证书验证通信双方的身份,以此来保证信息安全。其中证书中包含了证书所代表一端的公钥,以及一些其所具有基本信息,如机构名称、证书所作用域、证书的数字签名等,通过数字签名能够校验证书的真实性。通信的内容使用对称加密的方式进行加密,通信两端约定好通信密码后,通过公钥对密码进行加密传输,只有该公钥对应的私钥,也就是通信的另一端能够解密获取通信密码,这样既保证了通信安全,也使加密性能和时间成本可控。
HTTPS既支持单向认证,也支持双向认证,所谓的单向认证即只校验服务端证书的有效性,而双向认证则表示既校验服务端证书的有效性,同时也需要校验客户端证书的有效性。大部分情况下我们并不需要用到客户端证书,很多用户甚至没有客户端证书,但是某
些特定的环境下,如大额交易支付的场景下,也需要对用户的客户端证书进行校验,以保证通信的安全。
1、SSL/TLS
SSL协议的优势在于它与应用层协议独立无关,高层的应用层协议如HTTP、SSH,FTP等等,能透明的建立于SSL协议之上,在应
用层通信之前就已经完成加密算法、通信秘钥的协商以及服务端及客户端的认证工作,在此之后所有应用层协议所传输的数据都会被加密,
从而保证通信的私密性。
SSL的继任者TLS协议,是基于SSL协议的通用化协议,同样位于应用层和传输层之间,正逐步接替SSL称为下一代网络安全协议。
SSL/TLS协议均可以分为两层:一层为记录协议,一层为握手协议。记录协议建立在可靠的传输协议之上,提供数据封装、加密
解密、数据压缩、数据校验等基本功能。握手协议建立在记录协议之上,在实际的数据传输开始前,进行加密算法的协商,通信秘钥的
交换,通信双方的认证等工作。
2、java开发
SSL握手协议十分复杂,对于并非密码学专家的普通开发人员来说,理解交互过程不容易。对于普通开发人员来说,他们关心的并
不是如何实现SSL/TLS协议,而是如何才能让他们的程序以最简单的方式接入SSL/TLS强大的安全保护功能。JSSE正是这样的一个工具。
JSSE是Sun公司为了解决互联网信息安全传输提出的一个解决方案,它实现了SSL和TSL协议,包含了数据加密、服务器验证、
消息完整性和客户端验证等技术。通过使用JSSE简介的API,可以在服务端和客户端之间通过SSL/TSL协议安全地传输数据。
首先生成客户端证书、服务端证书。信任证书的导出:由于客户端与服务端证书都是在下面的CA所颁发,因此只需要将下面的CA的根证书作为信任库,就可以对客户端、服务端证书进行识别。
服务端:
public static void main(String[] args) throws Exception {
String serverKeyStoreFile = "c:\\_tmp\\catserver.keystore";
String serverKeyStorePwd = "catserverks";
String catServerKeyPwd = "catserver";
String serverTrustKeyStoreFile = "c:\\_tmp\\catservertrust.keystore";
String serverTrustKeyStorePwd = "catservertrustks";
KeyStore serverKeyStore = KeyStore.getInstance("JKS");
serverKeyStore.load(new FileInputStream(serverKeyStoreFile), serverKeyStorePwd.toCharArray());
KeyStore serverTrustKeyStore = KeyStore.getInstance("JKS");
serverTrustKeyStore.load(new FileInputStream(serverTrustKeyStoreFile), serverTrustKeyStorePwd.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(serverKeyStore, catServerKeyPwd.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(serverTrustKeyStore);
SSLContext sslContext = SSLContext.getInstance("TLSv1");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(SERVER_PORT);
sslServerSocket.setNeedClientAuth(true);
while (true) {
SSLSocket s = (SSLSocket)sslServerSocket.accept();
CatServer cs = new CatServer(s);
s.addHandshakeCompletedListener(cs);
new Thread(cs).start();
}
}
客户端:
public static void main(String[] args) throws Exception {
String clientKeyStoreFile = "c:\\_tmp\\foxclient.keystore";
String clientKeyStorePwd = "foxclientks";
String foxclientKeyPwd = "foxclient";
String clientTrustKeyStoreFile = "c:\\_tmp\\foxclienttrust.keystore";
String clientTrustKeyStorePwd = "foxclienttrustks";
KeyStore clientKeyStore = KeyStore.getInstance("JKS");
clientKeyStore.load(new FileInputStream(clientKeyStoreFile), clientKeyStorePwd.toCharArray());
KeyStore clientTrustKeyStore = KeyStore.getInstance("JKS");
clientTrustKeyStore.load(new FileInputStream(clientTrustKeyStoreFile), clientTrustKeyStorePwd.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(clientKeyStore, foxclientKeyPwd.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(clientTrustKeyStore);
SSLContext sslContext = SSLContext.getInstance("TLSv1");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
Socket socket = socketFactory.createSocket("localhost", CatServer.SERVER_PORT);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
send("hello", out);
send("exit", out);
receive(in);
socket.close();
}
3、部署HTTPS Web
tomcat单向认证配置:
编辑conf\server.xml文件,取消注释的HTTPS配置这一行。由于使用的keystore为PKCS#12格式,因此需要加参数
keystoreType=“pkcs12”,由于这里配置的是单向认证,只需要校验服务端证书的有效性,所有将clientAuth一项设置为false。
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" keystoreFile="E:/tomcat.keystore" keystorePass="123456" keystoreType=“pkcs12”/>
tomcat双向认证的配置:
相比较单向认证的配置,双向认证需要在其基础上进行些修改:
tomcat的server.xml文件增加信任库配置,truststoreFile指的是信任库地址,通过信任库中的根证书,服务端才能够对根证书签名的客户端进行识别。truststorePass指的是信任库的秘钥,truststoreType指的是信任库的格式,并且启用客户端认证,将
clientAuth设置为true。
<Connector port="8443"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" debug="0" scheme="https" secure="true"
clientAuth="true" sslProtocol="TLS"
keystoreFile="conf/tomcat.jks" keystorePass="123456" keystoreType="pkcs12"
truststoreFile="conf/truststore.jks" truststorePass="123456" truststoreType="JKS" />
在浏览器导入包含客户端证书与私钥的keystore文件。