HTTPS=HTTP+SSL/TLS,位於應用層。SSL/TLS協議自己是帶加密信息的傳輸層協議,數字證書正是爲這種協議提供相關加密/解密信息。java
SSL/TLS協議涉及多種加密算法,包括:
消息摘要算法:MD5和SHA1
對稱加密算法:RC二、RC四、IDEA、DES、Triple DES和AES
非對稱加密算法:RSA和DH
數字簽名算法:RSA和DSA算法
一、協商算法apache
服務端和客戶端進行握手協議的第一階段主要是協商算法,此時,產生隨機數RNC、RNStomcat
二、驗證證書服務器
客戶證書認證不必定必要,服務端身份得以認證,能夠進行服務端單向認證爲基礎的交互。dom
若是客戶證書也得以確認,那麼能夠進行雙向認證爲基礎的加密交互(eg:電子商務)。單元測試
三、產生密鑰測試
根據隨機數PMS、RNC、RNS,構建主密鑰MS加密
根據主密鑰構建會話密鑰,完成握手協議url
四、加密交互
進入正式會話階段,服務端和客戶端使用會話密鑰進行加密交互
一、證書導入
二、服務器配置
修改tomcat的conf/server.xml文件,並打開SSL/TLS的註釋,並配置密鑰庫文件keystoreFile
,和密鑰庫密碼keysotrePass
,密鑰庫類型參數keystoreType
(默認JKS)
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" keystoreFile="D:\MyData\majx2\crazyxing.keystore.old" keysotrePass="123456" />
備註:若是構建雙向認證,clientAuth需設置爲true
三、代碼驗證
經過一個本身實現的客戶端訪問上述服務。
import java.io.FileInputStream; import java.security.KeyStore; import java.security.SecureRandom; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; public abstract class HTTPSCoder { /** * 協議 */ public static final String PROTOCOL = "TLS"; /** * 得到KeyStore * * @param keyStorePath * 密鑰庫路徑 * @param password * 密碼 * @return KeyStore 密鑰庫 * @throws Exception */ private static KeyStore getKeyStore(String keyStorePath, String password) throws Exception { // 實例化密鑰庫 KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); // 得到密鑰庫文件流 FileInputStream is = new FileInputStream(keyStorePath); // 加載密鑰庫 ks.load(is, password.toCharArray()); // 關閉密鑰庫文件流 is.close(); return ks; } /** * 得到SSLSocektFactory * * @param password * 密碼 * @param keyStorePath * 密鑰庫路徑 * @param trustStorePath * 信任庫路徑 * @return SSLSocketFactory * @throws Exception */ private static SSLSocketFactory getSSLSocketFactory(String password, String keyStorePath, String trustStorePath) throws Exception { // 實例化密鑰庫 KeyManagerFactory keyManagerFactory = KeyManagerFactory .getInstance(KeyManagerFactory.getDefaultAlgorithm()); // 得到密鑰庫 KeyStore keyStore = getKeyStore(keyStorePath, password); // 初始化密鑰工廠 keyManagerFactory.init(keyStore, password.toCharArray()); // 實例化信任庫 TrustManagerFactory trustManagerFactory = TrustManagerFactory .getInstance(TrustManagerFactory.getDefaultAlgorithm()); // 得到信任庫 KeyStore trustStore = getKeyStore(trustStorePath, password); // 初始化信任庫 trustManagerFactory.init(trustStore); // 實例化SSL上下文 SSLContext ctx = SSLContext.getInstance(PROTOCOL); // 初始化SSL上下文 ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory .getTrustManagers(), new SecureRandom()); // 得到SSLSocketFactory return ctx.getSocketFactory(); } /** * 爲HttpsURLConnection配置SSLSocketFactory * * @param conn * HttpsURLConnection * @param password * 密碼 * @param keyStorePath * 密鑰庫路徑 * @param trustKeyStorePath * 信任庫路徑 * @throws Exception */ public static void configSSLSocketFactory(HttpsURLConnection conn, String password, String keyStorePath, String trustKeyStorePath) throws Exception { // 得到SSLSocketFactory SSLSocketFactory sslSocketFactory = getSSLSocketFactory(password, keyStorePath, trustKeyStorePath); // 設置SSLSocketFactory conn.setSSLSocketFactory(sslSocketFactory); } }
相應的單元測試
import org.junit.Test; import javax.net.ssl.HttpsURLConnection; import java.io.DataInputStream; import java.net.URL; import static org.junit.Assert.assertNotNull; public class HTTPSCoderTest { /** * 密鑰庫/信任庫密碼 */ private String password = "123456"; /** * 密鑰庫文件路徑 */ private String keyStorePath = "D:/MyData/majx2/crazyxing.keystore.old"; /** * 信任庫文件路徑 */ private String trustStorePath = "D:/MyData/majx2/crazyxing.keystore.old"; /** * 訪問地址 */ private String httpsUrl = "https://www.crazyxing.com:8443/ssl/"; /** * HTTPS驗證 * * @throws Exception */ @Test public void test() throws Exception { // 創建HTTPS連接 URL url = new URL(httpsUrl); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); conn.setRequestMethod("GET"); // 打開輸入輸出流 conn.setDoInput(true); // conn.setDoOutput(true); // 爲HttpsURLConnection配置SSLSocketFactory HTTPSCoder.configSSLSocketFactory(conn, password, keyStorePath, trustStorePath); // 鑑別內容長度 int length = conn.getContentLength(); byte[] data = null; // 若是內容長度爲-1,則放棄解析 if (length != -1) { DataInputStream dis = new DataInputStream(conn.getInputStream()); data = new byte[length]; dis.readFully(data); dis.close(); System.err.println(new String(data)); } conn.disconnect(); // 驗證 assertNotNull(data); } }
一、導入證書
導入客戶端證書到我的TAB
導入CA證書到財新人的根證書頒發機構
二、服務器配置
修改tomcat的conf/server.xml文件,並打開SSL/TLS的註釋,並配置密鑰庫文件keystoreFile、truststoreFile,和密鑰庫密碼keysotrePass、truststorePass,密鑰庫類型參數keystoreType、truststoreType,clientAuth設置爲true
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" clientAuth="true" sslProtocol="TLS" keystoreFile="D:\MyData\majx2\demoCA\certs\server.p12" keystorePass="123456" keystoreType="PKCS12" truststoreFile="D:\MyData\majx2\demoCA\certs\ca.p12" truststorePass="123456" truststoreType="PKCS12" />
三、代碼驗證
經過一個本身實現的客戶端訪問上述服務。
import java.io.FileInputStream; import java.security.KeyStore; import java.security.SecureRandom; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; public abstract class HTTPSCoder { /** * 協議 */ public static final String PROTOCOL = "TLS"; /** * 得到KeyStore * * @param keyStorePath * 密鑰庫路徑 * @param password * 密碼 * @return KeyStore 密鑰庫 * @throws Exception */ private static KeyStore getKeyStore(String keyStorePath, String password) throws Exception { // 實例化密鑰庫 KeyStore ks = KeyStore.getInstance("PKCS12"); // KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); // 得到密鑰庫文件流 FileInputStream is = new FileInputStream(keyStorePath); // 加載密鑰庫 ks.load(is, password.toCharArray()); // 關閉密鑰庫文件流 is.close(); return ks; } /** * 得到SSLSocektFactory * * @param password * 密碼 * @param keyStorePath * 密鑰庫路徑 * @param trustStorePath * 信任庫路徑 * @return SSLSocketFactory * @throws Exception */ private static SSLSocketFactory getSSLSocketFactory(String password, String keyStorePath, String trustStorePath) throws Exception { // 實例化密鑰庫 KeyManagerFactory keyManagerFactory = KeyManagerFactory .getInstance(KeyManagerFactory.getDefaultAlgorithm()); // 得到密鑰庫 KeyStore keyStore = getKeyStore(keyStorePath, password); // 初始化密鑰工廠 keyManagerFactory.init(keyStore, password.toCharArray()); // 實例化信任庫 TrustManagerFactory trustManagerFactory = TrustManagerFactory .getInstance(TrustManagerFactory.getDefaultAlgorithm()); // 得到信任庫 KeyStore trustStore = getKeyStore(trustStorePath, password); // 初始化信任庫 trustManagerFactory.init(trustStore); // 實例化SSL上下文 SSLContext ctx = SSLContext.getInstance(PROTOCOL); // 初始化SSL上下文 ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory .getTrustManagers(), new SecureRandom()); // 得到SSLSocketFactory return ctx.getSocketFactory(); } /** * 爲HttpsURLConnection配置SSLSocketFactory * * @param conn * HttpsURLConnection * @param password * 密碼 * @param keyStorePath * 密鑰庫路徑 * @param trustKeyStorePath * 信任庫路徑 * @throws Exception */ public static void configSSLSocketFactory(HttpsURLConnection conn, String password, String keyStorePath, String trustKeyStorePath) throws Exception { // 得到SSLSocketFactory SSLSocketFactory sslSocketFactory = getSSLSocketFactory(password, keyStorePath, trustKeyStorePath); // 設置SSLSocketFactory conn.setSSLSocketFactory(sslSocketFactory); } }
相應的單元測試
import org.junit.Test; import javax.net.ssl.HttpsURLConnection; import java.io.DataInputStream; import java.net.URL; import static org.junit.Assert.assertNotNull; public class HTTPSCoderTest { /** * 密鑰庫/信任庫密碼 */ private String password = "123456"; /** * 密鑰庫文件路徑 */ private String keyStorePath = "D:\\MyData\\majx2\\demoCA\\certs\\server.p12"; /** * 信任庫文件路徑 */ private String trustStorePath = "D:\\MyData\\majx2\\demoCA\\certs\\ca.p12"; /** * 訪問地址 */ private String httpsUrl = "https://www.crazyxing.com:8443/ssl/"; /** * HTTPS驗證 * * @throws Exception */ @Test public void test() throws Exception { // 創建HTTPS連接 URL url = new URL(httpsUrl); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); // conn.setRequestMethod(method); // 打開輸入輸出流 conn.setDoInput(true); // conn.setDoOutput(true); // 爲HttpsURLConnection配置SSLSocketFactory HTTPSCoder.configSSLSocketFactory(conn, password, keyStorePath, trustStorePath); // 鑑別內容長度 int length = conn.getContentLength(); byte[] data = null; // 若是內容長度爲-1,則放棄解析 if (length != -1) { DataInputStream dis = new DataInputStream(conn.getInputStream()); data = new byte[length]; dis.readFully(data); dis.close(); System.err.println(new String(data)); } conn.disconnect(); // 驗證 assertNotNull(data); } }