国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > Java > 正文

Java實(shí)現(xiàn)SSL雙向認(rèn)證的方法

2019-11-26 13:57:44
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

本文實(shí)例講述了Java實(shí)現(xiàn)SSL雙向認(rèn)證的方法。分享給大家供大家參考,具體如下:

我們常見(jiàn)的SSL驗(yàn)證較多的只是驗(yàn)證我們的服務(wù)器是否是真實(shí)正確的,當(dāng)然如果你訪問(wèn)的URL壓根就錯(cuò)了,那誰(shuí)也沒(méi)有辦法。這個(gè)就是所謂的SSL單向認(rèn)證。

但是實(shí)際中,我們有可能還會(huì)驗(yàn)證客戶端是否符合要求,也就是給我們每個(gè)用戶頒發(fā)一個(gè)證書(shū),比且每個(gè)數(shù)字證書(shū)都是唯一的,不公開(kāi)的。這樣就能通過(guò)這個(gè)數(shù)字證書(shū)保證當(dāng)前訪問(wèn)我服務(wù)器的這個(gè)用戶是經(jīng)過(guò)服務(wù)器認(rèn)可的,其他人不可訪問(wèn)。

雙向認(rèn)證 從第一個(gè)層面上 確保了服務(wù)器 與客戶端 都是互相認(rèn)可的。那么他們之間要進(jìn)行通信,就會(huì)在通信協(xié)議上附加SSL協(xié)議,確保通信的內(nèi)容是加密的,即使是sniffer這樣的網(wǎng)絡(luò)嗅探工具看到的都是亂碼。以后給大家演示下不加密的情況下,用sniffer看到的是什么。恐怕這樣你就能提高警惕了。

以下內(nèi)容從網(wǎng)絡(luò)上摘抄 加以實(shí)際驗(yàn)證后修改的。

模擬場(chǎng)景:

Server端和Client端通信,需要進(jìn)行授權(quán)和身份的驗(yàn)證,即Client只能接受Server的消息,Server只能接受Client的消息。

實(shí)現(xiàn)技術(shù):

JSSE(Java Security Socket Extension)

是Sun為了解決在Internet上的安全通訊而推出的解決方案。它實(shí)現(xiàn)了SSL和TSL(傳輸層安全)協(xié)議。在JSSE中包含了數(shù)據(jù)加密,服務(wù)器驗(yàn)證,消息完整性和客戶端驗(yàn)證等技術(shù)。通過(guò)使用JSSE,開(kāi)發(fā)人員可以在客戶機(jī)和服務(wù)器之間通過(guò)TCP/IP協(xié)議安全地傳輸數(shù)據(jù)。

為了實(shí)現(xiàn)消息認(rèn)證。

Server需要:

1)KeyStore: 其中保存服務(wù)端的私鑰
2)Trust KeyStore:其中保存客戶端的授權(quán)證書(shū)

同樣,Client需要:

1)KeyStore:其中保存客戶端的私鑰
2)Trust KeyStore:其中保存服務(wù)端的授權(quán)證書(shū)
在這里我還是推薦使用Java自帶的keytool命令,去生成這樣信息文件。當(dāng)然目前非常流行的開(kāi)源的生成SSL證書(shū)的還有OpenSSL。OpenSSL用C語(yǔ)言編寫(xiě),跨系統(tǒng)。但是我們可能在以后的過(guò)程中用java程序生成證書(shū)的方便性考慮,還是用JDK自帶的keytool。

1)生成服務(wù)端私鑰,并且導(dǎo)入到服務(wù)端KeyStore文件中

keytool -genkey -alias serverkey -keystore kserver.keystore
過(guò)程中,分別需要填寫(xiě),根據(jù)需求自己設(shè)置就行

keystore密碼:123456
名字和姓氏:jin
組織單位名稱:none
組織名稱:none
城市或區(qū)域名稱:BJ
州或省份名稱:BJ
國(guó)家代碼:CN

serverkey私鑰的密碼,不填寫(xiě)和keystore的密碼一致。這里千萬(wàn)注意,直接回車就行了,不用修改密碼。否則在后面的程序中以及無(wú)法直接應(yīng)用這個(gè)私鑰,會(huì)報(bào)錯(cuò)。

就可以生成kserver.keystore文件

server.keystore是給服務(wù)端用的,其中保存著自己的私鑰

2)根據(jù)私鑰,導(dǎo)出服務(wù)端證書(shū)

keytool -export -alias serverkey -keystore kserver.keystore -file server.crt
server.crt就是服務(wù)端的證書(shū)

3)將服務(wù)端證書(shū),導(dǎo)入到客戶端的Trust KeyStore中

keytool -import -alias serverkey -file server.crt -keystore tclient.keystore
tclient.keystore是給客戶端用的,其中保存著受信任的證書(shū)

采用同樣的方法,生成客戶端的私鑰,客戶端的證書(shū),并且導(dǎo)入到服務(wù)端的Trust KeyStore中

1)keytool -genkey -alias clientkey -keystore kclient.keystore
2)keytool -export -alias clientkey -keystore kclient.keystore -file client.crt
3)keytool -import -alias clientkey -file client.crt -keystore tserver.keystore

如此一來(lái),生成的文件分成兩組

服務(wù)端保存:kserver.keystore tserver.keystore
客戶端保存:kclient.keystore  tclient.kyestore

以下是通過(guò)Java Socket通信程序來(lái)驗(yàn)證我們生成的證書(shū)是否可用。

客戶端:

package examples.ssl;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.security.KeyStore;import javax.net.ssl.KeyManagerFactory;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLSocket;import javax.net.ssl.TrustManagerFactory;/** * SSL Client * */public class SSLClient { private static final String DEFAULT_HOST     = "127.0.0.1"; private static final int DEFAULT_PORT     = 7777; private static final String CLIENT_KEY_STORE_PASSWORD  = "123456"; private static final String CLIENT_TRUST_KEY_STORE_PASSWORD = "123456"; private SSLSocket   sslSocket; /**  * 啟動(dòng)客戶端程序  *  * @param args  */ public static void main(String[] args) {  SSLClient client = new SSLClient();  client.init();  client.process(); } /**  * 通過(guò)ssl socket與服務(wù)端進(jìn)行連接,并且發(fā)送一個(gè)消息  */ public void process() {  if (sslSocket == null) {   System.out.println("ERROR");   return;  }  try {   InputStream input = sslSocket.getInputStream();   OutputStream output = sslSocket.getOutputStream();   BufferedInputStream bis = new BufferedInputStream(input);   BufferedOutputStream bos = new BufferedOutputStream(output);   bos.write("Client Message".getBytes());   bos.flush();   byte[] buffer = new byte[20];   bis.read(buffer);   System.out.println(new String(buffer));   sslSocket.close();  } catch (IOException e) {   System.out.println(e);  } } /**  * <ul>  * <li>ssl連接的重點(diǎn):</li>  * <li>初始化SSLSocket</li>  * <li>導(dǎo)入客戶端私鑰KeyStore,導(dǎo)入客戶端受信任的KeyStore(服務(wù)端的證書(shū))</li>  * </ul>  */ public void init() {  try {   SSLContext ctx = SSLContext.getInstance("SSL");   KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");   TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");   KeyStore ks = KeyStore.getInstance("JKS");   KeyStore tks = KeyStore.getInstance("JKS");   ks.load(new FileInputStream("E://kclient.keystore"), CLIENT_KEY_STORE_PASSWORD.toCharArray());   tks.load(new FileInputStream("E://tclient.keystore"), CLIENT_TRUST_KEY_STORE_PASSWORD.toCharArray());   kmf.init(ks, CLIENT_KEY_STORE_PASSWORD.toCharArray());   tmf.init(tks);   ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);   sslSocket = (SSLSocket) ctx.getSocketFactory().createSocket(DEFAULT_HOST, DEFAULT_PORT);  } catch (Exception e) {   System.out.println(e);  } }}

服務(wù)器端:

package examples.ssl;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;import java.security.KeyStore;import javax.net.ssl.KeyManagerFactory;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLServerSocket;import javax.net.ssl.TrustManagerFactory;/*********************************************************************************************************************** * <ul> * <li>1)生成服務(wù)端私鑰</li> * <li>keytool -genkey -alias serverkey -keystore kserver.keystore</li> * <li>2)根據(jù)私鑰,到處服務(wù)端證書(shū)</li> * <li>keytool -exoport -alias serverkey -keystore kserver.keystore -file server.crt</li> * <li>3)把證書(shū)加入到客戶端受信任的keystore中</li> * <li>keytool -import -alias serverkey -file server.crt -keystore tclient.keystore</li> * </ul> **********************************************************************************************************************//** * SSL Server * */public class SSLServer { private static final int DEFAULT_PORT     = 7777; private static final String SERVER_KEY_STORE_PASSWORD  = "123456"; private static final String SERVER_TRUST_KEY_STORE_PASSWORD = "123456"; private SSLServerSocket  serverSocket; /**  * 啟動(dòng)程序  *  * @param args  */ public static void main(String[] args) {  SSLServer server = new SSLServer();  server.init();  server.start(); } /**  * <ul>  * <li>聽(tīng)SSL Server Socket</li>  * <li> 由于該程序不是演示Socket監(jiān)聽(tīng),所以簡(jiǎn)單采用單線程形式,并且僅僅接受客戶端的消息,并且返回客戶端指定消息</li>  * </ul>  */ public void start() {  if (serverSocket == null) {   System.out.println("ERROR");   return;  }  while (true) {   try {    Socket s = serverSocket.accept();    InputStream input = s.getInputStream();    OutputStream output = s.getOutputStream();    BufferedInputStream bis = new BufferedInputStream(input);    BufferedOutputStream bos = new BufferedOutputStream(output);    byte[] buffer = new byte[20];    bis.read(buffer);    System.out.println(new String(buffer));    bos.write("Server Echo".getBytes());    bos.flush();    s.close();   } catch (Exception e) {    System.out.println(e);   }  } } /**  * <ul>  * <li>ssl連接的重點(diǎn):</li>  * <li>初始化SSLServerSocket</li>  * <li>導(dǎo)入服務(wù)端私鑰KeyStore,導(dǎo)入服務(wù)端受信任的KeyStore(客戶端的證書(shū))</li>  * </ul>  */ public void init() {  try {   SSLContext ctx = SSLContext.getInstance("SSL");   KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");   TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");   KeyStore ks = KeyStore.getInstance("JKS");   KeyStore tks = KeyStore.getInstance("JKS");   ks.load(new FileInputStream("E://kserver.keystore"), SERVER_KEY_STORE_PASSWORD.toCharArray());   tks.load(new FileInputStream("E://tserver.keystore"), SERVER_TRUST_KEY_STORE_PASSWORD.toCharArray());   kmf.init(ks, SERVER_KEY_STORE_PASSWORD.toCharArray());   tmf.init(tks);   ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);   serverSocket = (SSLServerSocket) ctx.getServerSocketFactory().createServerSocket(DEFAULT_PORT);   serverSocket.setNeedClientAuth(true);  } catch (Exception e) {   e.printStackTrace();  } }}

更多關(guān)于java相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點(diǎn)技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總

希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 报价| 绥中县| 安溪县| 库尔勒市| 望都县| 长兴县| 四平市| 错那县| 沂南县| 洛扎县| 商南县| 克什克腾旗| 卢龙县| 麦盖提县| 垫江县| 泰宁县| 鹿泉市| 明星| 曲阜市| 玉门市| 如东县| 紫金县| 西贡区| 华池县| 天水市| 霸州市| 岳西县| 淮北市| 万山特区| 会同县| 渭南市| 礼泉县| 肥西县| 昌黎县| 徐闻县| 固阳县| 镇赉县| 德格县| 湖州市| 吴堡县| 从江县|