使用SSL構建安全的Socket(轉)
?SSL(安全套接層)是Netscape公司在1994年開發的,最初用于WEB瀏覽器,為瀏覽器與服務器間的數據傳遞提供安全保障,提供了加密、來源認證和數據完整性的功能?,F在SSL3.0得到了普遍的使用,它的改進版TLS(傳輸層安全)已經成為互聯網標準。SSL本身和TCP套接字連接是很相似的,在協議棧中,SSL可以被簡單的看作是安全的TCP連接,但是某些TCP連接的特性它是不支持的,比如帶外數據(out-of-bound)。
?在構建基于Socket的C/S程序時,通過添加對SSL的支持來保障數據安全和完整是不錯的方法。完善的Java為我們提供了簡單的實現方法:JSSE(Java安全套接字擴展)。JSSE是一個純Java實現的SSL和TLS協議框架,抽象了SSL和TLS復雜的算法,使安全問題變得簡單。JSSE已經成為J2SE1.4版本中的標準組件,支持SSL?3.0和TLS?1.0。我們將通過一個具體的例子演示JSSE的一些基本應用。例子中的服務器端將打開一個SSL?Socket,只有持有指定證書的客戶端可以與它連接,所有的數據傳遞都是加密的。
?構造一個SSLSocket是非常簡單的:
?SSLServerSocketFactory?factory=(SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
?SSLServerSocket?server?=?(SSLServerSocket)?factory.createServerSocket(portNumber);
?SSLSocket?socket?=?(SSLSocket);
?但是執行這樣的程序會產生一個異常,報告找不到可信任的證書。SSLSocket和普通的Socket是不一樣的,它需要一個證書來進行安全認證。
?一、?證書
?生成一個CA證書,在命令行下執行:
?keytool?–genkey?–keystore?SSLKey?–keyalg?rsa?–alias?SSL
?黑體部分是用戶可以自己指定的參數,第一個參數是要生成的證書的名字,第二個參數是證書的別名。rsa指明了我們使用的加密方法。
?系統會要求輸入證書發放者的信息,逐項輸入即可,如下圖:
??
???系統生成的文件命將會和證書名相同。證書可以提交給權威CA認證組織審核,如果通過審核,組織會提供信任擔保,向客戶擔保你的連接是安全的。當然這不是必須的。在我們的例子中會把證書直接打包到客戶端程序中,保證客戶端是授權用戶,避免偽造客戶,所以不需要提交審核。
?二、?服務器端
?現在可以編寫服務器端的代碼,與普通的Socket代碼不同,我們需要在程序中導入證書,并使用該證書構造SSLSocket。需要的說明的是:
?●KeyStore?ks=KeyStore.getInstance("JKS");
?訪問Java密鑰庫,JKS是keytool創建的Java密鑰庫,保存密鑰。
?●?KeyManagerFactory?kmf=KeyManagerFactory.getInstance("SunX509");
?創建用于管理JKS密鑰庫的X.509密鑰管理器。
?●?SSLContext?sslContext=SSLContext.getInstance("SSLv3");
?構造SSL環境,指定SSL版本為3.0,也可以使用TLSv1,但是SSLv3更加常用。
?●sslContext.init(kmf.getKeyManagers(),null,null);
?初始化SSL環境。第二個參數是告訴JSSE使用的可信任證書的來源,設置為null是從javax.net.ssl.trustStore中獲得證書。第三個參數是JSSE生成的隨機數,這個參數將影響系統的安全性,設置為null是個好選擇,可以保證JSSE的安全性。
?完整代碼如下:


??2

??3

??4

??5

??6

??7

??8

??9

?10

?11

?12

?13

?14



?15

?16

?17

?18


?19

?20

?21

?22

?23



?24

?25

?26

?27

?28


?29

?30

?31

?32

?33

?34



?35

?36

?37



?38

?39

?40

?41

?42

?43

?44

?45

?46

?47

?48

?49

?50

?51

?52

?53

?54

?55

?56

?57

?58

?59

?60

?61

?62

?63



?64

?65

?66

?67

?68

?69

?70

?71



?72

?73



?74

?75


?76

?77

?78



?79

?80

?81

?82

?83

?84

?85

?86



?87

?88

?89

?90

?91

?92


?93

?94

?95

?96

?97



?98

?99

100

101

102


103

104

105

106

107



108

109



110

111

112

113

114

115

116

117

118



119

120

121

122

123

124


125

126

127

128

129



130

131



132

133

134

135

136



137

138

139

140

141

142

??將我們剛才生成的證書放到程序所在的目錄下,上面的代碼就可以在編譯之后執行:
?java?org.ec107.ssl.SSLServer
?在8266端口等待連接…
?三、?客戶端
?客戶端的代碼相對簡單,我們可以不在程序中指定SSL環境,而是在執行客戶端程序時指定。需要注意的是客戶端并沒有導入證書,而是采用了默認的工廠方法構造SSLSocket:
?●?SSLSocketFactory?factory=(SSLSocketFactory)SSLSocketFactory.getDefault();
?構造默認的工廠方法
?●Socket?s=factory.createSocket("localhost",port);
?打開一個SSLSocket連接
?












































?把服務器產生的證書(SSLKey)拷貝到程序所在的目錄,執行這個程序的時候需要向javax.net.ssl.trustStore環境變量傳入證書名:
?java?–Djavax.net.ssl.trustStore=SSLKey?org.ec107.ssl.SSLClient
?可以在服務器的控制臺看到客戶端發送過來的數據。
?執行客戶端可以有另一種方法,把證書拷貝到java?home/lib/security目錄下,名字改為jssecacerts,然后可以直接執行客戶端:
?java?org.ec107.ssl.SSLClient
?程序會自動的到上述目錄下去尋找jssecacerts文件作為默認的證書。需要注意的是這里的java?home并不是我們在安裝J2SE時指定的那個JAVA_HOME。可以執行一個程序來得到java?home的位置:
?public?class?GetJavaHome
?{
???public?static?void?main(String?args[])
???{
?????System.out.println(System.getProperty(“java.home”));
???}
?}
?一般情況下(windows?2K)hava?home的位置是在C:Program?FilesJavaj2re1.4.0_02,相對的,證書就應該拷貝到C:Program?FilesJavaj2re1.4.0_02libsecurity下,如果安裝了自帶JDK的Java?IDE,比如JBuilder,情況可能會有不同。
???如果程序客戶在不持有證書的情況下直接進行連接,服務器端會產生運行時異常,不允許進行連接。
?運行環境:windows?2K?server,j2sdk1.4.1
posted on 2007-03-15 21:15 黑馬_2046 閱讀(1049) 評論(0) 編輯 收藏 所屬分類: 常用代碼