2013-01-05 77 views
2

我有一個簡單的服務器程序,收集來自開放無線網絡上衆多硬件設備的數據。我想確保誰連接到我的端口不能發送命令或監聽我的流量,所以我需要服務器來驗證客戶端。我找到了一些例子,但大多數似乎採取了從客戶端驗證服務器的方法。我不熟悉SSL和Socket編程。Java SSL套接字客戶端身份驗證

從客戶端我有

KeyStore keystore = KeyStore.getInstance("JKS"); 
keystore.load(new FileInputStream("KeyStore"), "password".toCharArray()); 
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 
tmf.init(keystore); 

SSLContext context = SSLContext.getInstance("TLS"); 
TrustManager[] trustManagers = tmf.getTrustManagers(); 

context.init(null, trustManagers, null); 

SSLSocketFactory sf = context.getSocketFactory(); 
return (SSLSocket) sf.createSocket(host, port); 

和服務器上我有

KeyStore ks = KeyStore.getInstance("JKS"); 
ks.load(newFileInputStream("server"),"password".toCharArray()); 
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 
kmf.init(ks, "password".toCharArray()); 
SSLContext sc = SSLContext.getInstance("SSL"); 
sc.init(kmf.getKeyManagers(), null, null); 
SSLServerSocketFactory ssf = sc.getServerSocketFactory(); 
server = (SSLServerSocket) ssf.createServerSocket(this.port); 

我不完全相信一切都在做,但我發現的例子是2路認證,所以一些矯枉過正。我想我只需要其中的一段代碼,但是不太瞭解SSL,不知道哪一段代碼。哪一方需要密鑰存儲?誰需要鑰匙和證書?由於

+1

雙向身份驗證不是「矯枉過正」,它是服務器身份驗證和客戶端身份驗證,如果您不希望其他人監聽您的流量,則這是您所需要的。如果服務器需要信任這些設備,那麼這些設備也需要信任服務器? – EJP

+0

感謝您的回覆。我最關心的是有人連接到我的端口並嘗試向服務器發送命令。我並不關心服務器身份驗證,因爲這些設備會長時間連接到服務器。我想我會通過單向保存來減少維護和複雜性。 – Shoe

回答

2

如果你只是想客戶端身份驗證添加到您現有的服務器認證,在你的服務器代碼末尾加上這一行:

server.setNeedClientAuth(true); 

如果你只希望服務器授權的客戶端,而不是副請在服務器中調用server.setUseClientMode(true),然後在客戶端上創建的SSLSocket上調用setUseClientMode(false),然後再返回。請注意,此選項意味着客戶端設備可能連接到其他人的服務器,並且無法知道它。

在任何一種情況下,服務器都需要一個信任庫(可以與其密鑰庫相同),並附帶一份客戶端安裝的證書副本。客戶將需要提供此證書的密鑰對。

+0

不確定你需要提及'server.setUseClientMode(true)',它只是讓這個答案比它需要更復雜。這也使TCP服務器成爲SSL/TLS客戶端,反之亦然,所以它不再是真正的客戶端證書認證。 – Bruno

+1

包含該部分是因爲提問者似乎只需要客戶端身份驗證 - 其中「客戶端」是指「TCP客戶端」,而不是「SSL/TLS客戶端」。我同意這不是正常的用例,但我想完全回答這個問題。 –