SSL的TCP通信
一切盡在代碼中,額,自己測試的小例子,感覺很有用,做個記錄。
服務器端:
</pre><pre name="code" class="java">package com.mpc.test.clazz;import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.security.KeyStore; import java.security.SecureRandom;import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.TrustManagerFactory;public class SSLTest {public static void main(String[] args) throws Exception {String key = "d:/keys/m.jks";// 定義服務器端要使用的證書String trust = "d:keys/trustclient.jks";// 定義服務器端要信任的證書/* 個人感覺,上面這兩個屬性在使用的時候完全可以定義為properties文件或者xml文件來使用 */KeyStore keyStore = KeyStore.getInstance("JKS");// 定義一個KeyStore用來存儲服務器的秘鑰文件keyStore.load(new FileInputStream(key), "123456".toCharArray());// 加載服務器端使用的證書,當然要輸入要打開加密文件的密碼了KeyStore trustStore = KeyStore.getInstance("JKS");// 定義一個KeyStore用來存儲服務器信任的證書文件trustStore.load(new FileInputStream(trust), "123456".toCharArray());// 加載服務器端信任的證書文件,當然也要輸入密碼的/** 額,其實keyStore和truststore都是Keystore的大家都看到了,就是保存的秘鑰文件不同而已了 */KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());/** 創建一個服務器的秘鑰管理工廠,KeyManagerFactory.* getDefaultAlgorithm* ()是指定的默認的算法,記得是RSA··輸出一下就OK了*/kmf.init(keyStore, "mipengcheng".toCharArray());/** 初始化,在初始化的時候需要自定秘鑰的密碼,* 這個在創建的時候指定的*/TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());/** 創建一個服務器信任證書的管理工廠* ,* 同樣指定了RSA的算法*/tmf.init(trustStore);/* 初始化,由于信任的是證書,不是秘鑰,所以不用指定密碼什么的了 */SSLContext sslc = SSLContext.getInstance("TLSv1");/** 獲得TLSv1版本的SSLContext,* 還有個ssl3的*/sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(),new SecureRandom());/* 用兩個工廠來初始化SSLContext */SSLServerSocketFactory sllFactory = sslc.getServerSocketFactory();/* 獲得服務器端口工廠 */SSLServerSocket serverSocket = (SSLServerSocket) sllFactory.createServerSocket(9999);/* 創建serverSocket,在9999端口監聽 *//* 這句很重要,是要開啟客戶端的安全證書驗證滴 */serverSocket.setNeedClientAuth(true);System.out.println("服務器已經啟動了........");while (true) {final Socket socket = serverSocket.accept();/** accept用來阻塞監聽線程,訪問一個處理一個*/System.out.println("接收到" + socket.getRemoteSocketAddress() + "的請求");new Thread(new MyThread(socket)).start();/* 創建新的線程用來處理接受到的socket */}}static class MyThread implements Runnable {private Socket socket;public MyThread(Socket socket) {super();this.socket = socket;}public void run() {/** 這里是對接受的請求的處理,沒什么東西了。 */try {System.out.println("服務器開始讀取數據=====");BufferedReader read = new BufferedReader(new InputStreamReader(socket.getInputStream()));PrintWriter out = new PrintWriter(socket.getOutputStream(),true);String message;while (null != (message = read.readLine())) {if (message.equals("end")) {out.println("agree");break;} else {System.out.println("結果" + message);out.println("服務器收到消息");}}System.out.println("服務器跳出循環");Thread.sleep(10000);out.close();read.close();} catch (Exception e) {e.printStackTrace();}}} }
客戶端:
package com.mpc.test.clazz;import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.security.KeyStore; import java.security.SecureRandom;import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory;public class SSLTestClient {public static void main(String[] args) throws Exception {/* 從這里開始======== */String key = "d:/keys/trustm.jks";String client = "d:/keys/client.jks";KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());keyStore.load(new FileInputStream(key), "123456".toCharArray());KeyStore clientStore = KeyStore.getInstance(KeyStore.getDefaultType());clientStore.load(new FileInputStream(client), "123456".toCharArray());TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());tmf.init(keyStore);KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());kmf.init(clientStore, "123456".toCharArray());SSLContext sslc = SSLContext.getInstance("TLSv1");sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(),new SecureRandom());/* 到這里結束======== *//** 上面注釋包圍的內容,和服務器端的一樣,只是這里變成了客戶端要使用的秘鑰,客戶端要信任的證書 */SSLSocketFactory sslSocketFactory = sslc.getSocketFactory();/* 獲得socketFactory */SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket("127.0.0.1", 9999);/* 訪問本機的9999端口 */socket.setKeepAlive(true);/*長連接···*//*下面都是消息的處理,沒什么東西了*/BufferedReader read = new BufferedReader(new InputStreamReader(socket.getInputStream()));PrintWriter out = new PrintWriter(socket.getOutputStream(), true);out.println("cilent message");String message;int i = 0;while (null != (message = read.readLine())) {System.out.println(message);i++;if (message.equals("agree")) {break;} else {}Thread.sleep(1000);out.println("cilent message");if (i == 5) {out.println("end");}}socket.close();out.close();read.close();System.out.println("客戶端跳出了while循環");} }
1.服務器端:
2.客戶端:
在項目中使用到的證書
關于證書的創建,這里以服務器端的秘鑰的創建和服務器要給客戶端使用的信任證書的創建為例:
使用jdk自帶的keytool來創建。
D:\keys>keytool -genkeypair -alias mkey -keyalg RSA -validity 7 -keystore m.jks 輸入密鑰庫口令: 再次輸入新口令: 您的名字與姓氏是什么?[Unknown]: mi 您的組織單位名稱是什么?[Unknown]: my 您的組織名稱是什么?[Unknown]: isis 您所在的城市或區域名稱是什么?[Unknown]: city 您所在的省/市/自治區名稱是什么?[Unknown]: state 該單位的雙字母國家/地區代碼是什么?[Unknown]: china CN=mi, OU=my, O=isis, L=city, ST=state, C=china是否正確?[否]: y輸入 <mkey> 的密鑰口令(如果和密鑰庫口令相同, 按回車): 再次輸入新口令:使用第一行的命令來生成證書,指定名字為m.jks;然后根據提示就可以創建服務器端的秘鑰了。
這條命令就把服務器端給客戶端驗證的證書的jks文件生成了。
客戶端的相關秘鑰,證書的生成也是一樣的。
本人才疏學淺,只是想折騰折騰,學習學習,如果有什么不對的,不足的地方,還請大家包涵,指教!
總結
- 上一篇: 懂得一些基本常识,就不会被《非酒精類致命
- 下一篇: [收藏]孔庆东-为何要唱样板戏