JSSE(Java Security Socket Extension
Java安全套接字擴展)是Sun為了解決在Internet上的安全通訊而推出的解決方案
它實現了SSL和TSL(傳輸層安全)協議
在JSSE中包含了數據加密
服務器驗證
消息完整性和客戶端驗證等技術
通過使用JSSE
開發人員可以在客戶機和服務器之間通過TCP/IP協議安全地傳輸數據
這篇文章主要描述如何使用JSSE接口來控制SSL連接
首先我通過一個簡單的客戶機/服務器程序來介紹如何利用JSSE進行編程
當建立客戶端時
我們需要配置KeyStore和TrustStore文件
這樣在程序中我們才可以從客戶端的文件系統中加載它們
然後文章將討論授權和身份驗證方面的問題
通過從KeyStore中選擇不同的授權
客戶端程序可以連接到不同的服務器
運行例子程序
下載例子程序
在運行JSSE程序前
你需要正確安裝JSSE
如果你安裝了J
SE
JSSE已經被自動安裝並配置好了
如果你使用的是其他版本的Java
你需要從官方站點上下載並安裝JSSE
安裝過程這裡就不再贅述
由於JSSE是在J
SE
中才成為標准的
並且J
SE
中的JSSE和以前的JSSE有一些細微的差別
而且文中的例子都是在J
SE
下調試的
因此推薦你使用J
SE
運行這些例子
在深入介紹JSSE之前
讓我們來一個簡單的客戶機/服務器程序
程序中包含了兩個文件
SimpleSSLServer和SimpleSSLClient
在運行程序之前
你需要配置下面這些KeyStore和TrestStore文件
· 一個客戶端的KeyStore文件
該文件中包含了對Alice和Bob的授權
· 一個服務器端的KeyStore文件
該文件中包含了對server的授權
· 一個名為clientTrust的客戶端TrustStore文件
該文件中包含了對server的授權
· 一個名為serverTrust的服務器端TrustStore文件
該文件中包含了對Alice和Bob的授權
使用keytool可以幫助你創建這些文件(該工具在Java的bin目錄下)
· 一個客戶端的KeyStore文件
該文件中包含了對Alice和Bob的授權
在命令窗口中輸入下面的命令
keytool
genkey
alias alice
keystore clientKeys
窗口中會出現下面的提示
根據提示輸入相應的信息
輸入keystore密碼
password
您的名字與姓氏是什麼?
[Unknown]
Alice
您的組織單位名稱是什麼?
[Unknown]
Development
您的組織名稱是什麼?
[Unknown]
DCQ
您所在的城市或區域名稱是什麼?
[Unknown]
ChongQing
您所在的州或省份名稱是什麼?
[Unknown]
ChongQing
該單位的兩字母國家代碼是什麼
[Unknown]
CH
CN=Alice
OU=Development
O=DCQ
L=ChongQing
ST=ChongQing
C=CH 正確嗎?
[否]
是
輸入的主密碼
(如果和 keystore 密碼相同
按回車)
通過相同的方式可以建立對Bob的授權
keytool
genkey
alias bob
keystore clientKeys
注意在名字與姓氏一欄中填寫Bob
在完成後可以鍵入下面的命令來檢測是否已經正確完成了授權
keytool
list
v
keystore clientKeys
· 一個服務器端的KeyStore文件
該文件中包含了對server的授權
在命令窗口中鍵入下面的命令
keytool
genkey
alias server
keystore serverKeys
注意將密碼設為password
名字與姓氏設定為Server
完成授權後同樣可以通過上面提到的命令來檢測
· 一個名為clientTrust的客戶端TrustStore文件
該文件中包含了對server的授權
以及一個名為serverTrust的服務器端TrustStore文件
該文件中包含了對Alice和Bob的授權
keytool
export
alias server
keystore clientKeys
file server
cer
輸入keystore密碼
password
保存在文件中的認證
keytool export alias alice keystore clientKeys file alicecer
輸入keystore密碼 password
保存在文件中的認證
keytool export alias bob keystore clientKeys file bobcer
輸入keystore密碼 password
保存在文件中的認證
這樣keytool就在當前目錄下創建了三個授權文件然後我們將servercer文件導入到clientTrust文件中將alicecer和bobcer導入到serverTruest文件中
keytool import alias server keystore clientTrust file servercer
keytool import alias alice keystore serverTrust file alicecer
keytool import alias bob keystore serverTrust file bobcer
到目前為止在當前目錄下包含clientKeysserverKeysclientTrustserverTrust四個文件完成了KeyStore和TrustStore的設置後就可以運行例子程序了首先需要運行服務器程序
java sslkeyStore=serverKeys
sslkeyStorePassword=password
ssltrustStore=serverTrust
ssltrustStorePassword=password SimpleSSLServer
在命令行中我們指定了keyStore屬性為serverKeys由於服務器程序需要獲得客戶端的授權信息我們指定trustStore為serverTrust這樣SSLSimpleServer就可以驗證由SSLSimpleClient提供的授權信息當服務器程序成功運行後你會看到下面的提示
SimpleSSLServer running on port
這時候服務器會等待客戶端發出建立連接的申請如果你希望在另一個端口上運行服務器程序可以在命令中指定port xxx參數其中xxx是端口號
然後在另一個命令窗口中運行客戶端程序
java sslkeyStore=clientKeys
sslkeyStorePassword=password
ssltrustStore=clientTrust
ssltrustStorePassword=password SimpleSSLClient
客戶端程序會試圖向本機的端口建立SSL連接同樣你可以通過port參數指定端口號也可以通過host參數指定主機名稱當連接成功後會出現下面的提示信息
Connected
同時在服務器端會提示用戶客戶端已經連接成功
SimpleSSLServer
讓我們先來看一下SimpleSSLServer在main()方法中程序獲得了缺省的SSLServerSocketFactory對象然後利用SSLServerSocketFactory創建一個SimpleSSLServer對象最後調用start()方法啟動SimpleSSLServer對象
SSLServerSocketFactory ssf=
(SSLServerSocketFactory)SSLServerSocketFactorygetDefault();
SimpleSSLServer server=new SimpleSSLServer(ssf port);
serverstart();
由於服務器是在一個單獨的線程中運行的main()方法啟動了服務器之後就退出了start()方法啟動了一個新的線程該線程執行run()方法中的代碼在run()方法中創建了一個SSLServerSocket對象然後設定服務器需要進行客戶端驗證
SSLServerSocket serverSocket= (SSLServerSocket)serverSocketFactorycreateServerSocket(port);
serverSocketsetNeedClientAuth(true);
調用run()方法後程序進入了一個死循環等待客戶端的連接申請循環中的每個Socket對應一個HandshakeCompletedListener對象(該對象是用來顯示客戶驗證信息中的標識名稱[distinguished name]的)Socket的InputStream對象被包裝在一個InputDisplayer對象中這個InputDisplayer對象運行在另外一個線程中用來將Socket接收到的數據發送到Systemout下面的代碼是SimpleSSLServer中的主循環體
while (true) {
String ident=StringvalueOf(id++);
//監聽連接請求
SSLSocket socket=(SSLSocket)serverSocketaccept();
//通過使用HandshakeCompletedListener對象程序進行授權驗證
HandshakeCompletedListener hcl=new SimpleHandshakeListener(ident);
socketaddHandshakeCompletedListener(hcl);
InputStream in=socketgetInputStream();
new InputDisplayer(ident in);
}
程序中的SimpleHandshakeListener類實現了HandshakeCompletedListerner接口在SimpleHandshakeListener類中實現了handshakeCompleted()方法該方法在SSL握手階段完成後將被JSSE調用它將顯示出客戶端的標識名稱
class SimpleHandshakeListener implements HandshakeCompletedListener
{
String ident;
/**
* 構造函數
*/
public SimpleHandshakeListener(String ident)
{
thisident=ident;
}
/**當SSL握手過程完成後該方法被激活 */
public void handshakeCompleted(HandshakeCompletedEvent event)
{
//顯示授權信息
try {
XCertificate
cert=(XCertificate)eventgetPeerCertificates()[];
String peer=certgetSubjectDN()getName();
Systemoutprintln(ident+: Request from +peer);
}
catch (SSLPeerUnverifiedException pue) {
Systemoutprintln(ident+: Peer
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19512.html