<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 5, 文章 - 0, 評(píng)論 - 1, 引用 - 0
    數(shù)據(jù)加載中……

    使用SSL構(gòu)建安全的Socket(轉(zhuǎn))

    bromon原創(chuàng)?版權(quán)所有

    ?SSL(安全套接層)是Netscape公司在1994年開發(fā)的,最初用于WEB瀏覽器,為瀏覽器與服務(wù)器間的數(shù)據(jù)傳遞提供安全保障,提供了加密、來源認(rèn)證和數(shù)據(jù)完整性的功能。現(xiàn)在SSL3.0得到了普遍的使用,它的改進(jìn)版TLS(傳輸層安全)已經(jīng)成為互聯(lián)網(wǎng)標(biāo)準(zhǔn)。SSL本身和TCP套接字連接是很相似的,在協(xié)議棧中,SSL可以被簡單的看作是安全的TCP連接,但是某些TCP連接的特性它是不支持的,比如帶外數(shù)據(jù)(out-of-bound)。

    ?在構(gòu)建基于Socket的C/S程序時(shí),通過添加對(duì)SSL的支持來保障數(shù)據(jù)安全和完整是不錯(cuò)的方法。完善的Java為我們提供了簡單的實(shí)現(xiàn)方法:JSSE(Java安全套接字?jǐn)U展)。JSSE是一個(gè)純Java實(shí)現(xiàn)的SSL和TLS協(xié)議框架,抽象了SSL和TLS復(fù)雜的算法,使安全問題變得簡單。JSSE已經(jīng)成為J2SE1.4版本中的標(biāo)準(zhǔn)組件,支持SSL?3.0和TLS?1.0。我們將通過一個(gè)具體的例子演示JSSE的一些基本應(yīng)用。例子中的服務(wù)器端將打開一個(gè)SSL?Socket,只有持有指定證書的客戶端可以與它連接,所有的數(shù)據(jù)傳遞都是加密的。

    ?構(gòu)造一個(gè)SSLSocket是非常簡單的:

    ?SSLServerSocketFactory?factory=(SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
    ?SSLServerSocket?server?=?(SSLServerSocket)?factory.createServerSocket(portNumber);
    ?SSLSocket?socket?=?(SSLSocket);

    ?但是執(zhí)行這樣的程序會(huì)產(chǎn)生一個(gè)異常,報(bào)告找不到可信任的證書。SSLSocket和普通的Socket是不一樣的,它需要一個(gè)證書來進(jìn)行安全認(rèn)證。

    ?一、?證書

    ?生成一個(gè)CA證書,在命令行下執(zhí)行:

    ?keytool?–genkey?–keystore?SSLKey?–keyalg?rsa?–alias?SSL

    ?黑體部分是用戶可以自己指定的參數(shù),第一個(gè)參數(shù)是要生成的證書的名字,第二個(gè)參數(shù)是證書的別名。rsa指明了我們使用的加密方法。

    ?系統(tǒng)會(huì)要求輸入證書發(fā)放者的信息,逐項(xiàng)輸入即可,如下圖:

    ??

    ???系統(tǒng)生成的文件命將會(huì)和證書名相同。證書可以提交給權(quán)威CA認(rèn)證組織審核,如果通過審核,組織會(huì)提供信任擔(dān)保,向客戶擔(dān)保你的連接是安全的。當(dāng)然這不是必須的。在我們的例子中會(huì)把證書直接打包到客戶端程序中,保證客戶端是授權(quán)用戶,避免偽造客戶,所以不需要提交審核。

    ?二、?服務(wù)器端

    ?現(xiàn)在可以編寫服務(wù)器端的代碼,與普通的Socket代碼不同,我們需要在程序中導(dǎo)入證書,并使用該證書構(gòu)造SSLSocket。需要的說明的是:

    ?●KeyStore?ks=KeyStore.getInstance("JKS");

    ?訪問Java密鑰庫,JKS是keytool創(chuàng)建的Java密鑰庫,保存密鑰。

    ?●?KeyManagerFactory?kmf=KeyManagerFactory.getInstance("SunX509");

    ?創(chuàng)建用于管理JKS密鑰庫的X.509密鑰管理器。

    ?●?SSLContext?sslContext=SSLContext.getInstance("SSLv3");

    ?構(gòu)造SSL環(huán)境,指定SSL版本為3.0,也可以使用TLSv1,但是SSLv3更加常用。

    ?●sslContext.init(kmf.getKeyManagers(),null,null);

    ?初始化SSL環(huán)境。第二個(gè)參數(shù)是告訴JSSE使用的可信任證書的來源,設(shè)置為null是從javax.net.ssl.trustStore中獲得證書。第三個(gè)參數(shù)是JSSE生成的隨機(jī)數(shù),這個(gè)參數(shù)將影響系統(tǒng)的安全性,設(shè)置為null是個(gè)好選擇,可以保證JSSE的安全性。

    ?完整代碼如下:

    ??1/*
    ??2?*SSL?Socket的服務(wù)器端
    ??3?*@Author?Bromon
    ??4?*/

    ??5
    ??6?package?org.ec107.ssl;
    ??7
    ??8?import?java.net.*;
    ??9?import?javax.net.ssl.*;
    ?10?import?java.io.*;
    ?11?import?java.security.*;
    ?12
    ?13?public?class?SSLServer
    ?14?{
    ?15??static?int?port=8266;??//系統(tǒng)將要監(jiān)聽的端口號(hào),82.6.6是偶以前女朋友的生日^_^
    ?16??static?SSLServerSocket?server;
    ?17??
    ?18??/*
    ?19??*構(gòu)造函數(shù)
    ?20??*/

    ?21??
    ?22??public?SSLServer()
    ?23??{
    ?24???
    ?25??}

    ?26??
    ?27??
    ?28??/*
    ?29??*@param?port?監(jiān)聽的端口號(hào)
    ?30??*@return?返回一個(gè)SSLServerSocket對(duì)象
    ?31??*/

    ?32??
    ?33??private?static?SSLServerSocket?getServerSocket(int?thePort)
    ?34??{
    ?35???SSLServerSocket?s=null;
    ?36???try
    ?37???{
    ?38????String?key="SSLKey";??//要使用的證書名
    ?39
    ?40????char?keyStorePass[]="12345678".toCharArray();??//證書密碼
    ?41
    ?42????char?keyPassword[]="12345678".toCharArray();??//證書別稱所使用的主要密碼
    ?43
    ?44????KeyStore?ks=KeyStore.getInstance("JKS");??//創(chuàng)建JKS密鑰庫
    ?45
    ?46????ks.load(new?FileInputStream(key),keyStorePass);
    ?47
    ?48????//創(chuàng)建管理JKS密鑰庫的X.509密鑰管理器
    ?49????KeyManagerFactory?kmf=KeyManagerFactory.getInstance("SunX509");
    ?50
    ?51????kmf.init(ks,keyPassword);
    ?52
    ?53????SSLContext?sslContext=SSLContext.getInstance("SSLv3");
    ?54
    ?55????sslContext.init(kmf.getKeyManagers(),null,null);
    ?56??
    ?57????//根據(jù)上面配置的SSL上下文來產(chǎn)生SSLServerSocketFactory,與通常的產(chǎn)生方法不同
    ?58????SSLServerSocketFactory?factory=sslContext.getServerSocketFactory();
    ?59
    ?60????s=(SSLServerSocket)factory.createServerSocket(thePort);
    ?61
    ?62???}
    catch(Exception?e)
    ?63???{
    ?64????System.out.println(e);
    ?65???}

    ?66???return(s);
    ?67??}

    ?68??
    ?69??
    ?70??public?static?void?main(String?args[])
    ?71??{
    ?72???try
    ?73???{
    ?74????server=getServerSocket(port);
    ?75????System.out.println("在”+port+”端口等待連接");
    ?76
    ?77????while(true)
    ?78????{
    ?79?????SSLSocket?socket=(SSLSocket)server.accept();
    ?80?????
    ?81?????//將得到的socket交給CreateThread對(duì)象處理,主線程繼續(xù)監(jiān)聽
    ?82?????new?CreateThread(socket);
    ?83?????
    ?84????}

    ?85???}
    catch(Exception?e)
    ?86???{
    ?87????System.out.println("main方法錯(cuò)誤80:"+e);
    ?88???}

    ?89??}

    ?90?}

    ?91
    ?92?/*
    ?93?*內(nèi)部類,獲得主線程的socket連接,生成子線程來處理
    ?94?*/

    ?95
    ?96?class?CreateThread?extends?Thread
    ?97?{
    ?98??static?BufferedReader?in;
    ?99??static?PrintWriter?out;
    100??static?Socket?s;
    101??
    102??/*
    103??*構(gòu)造函數(shù),獲得socket連接,初始化in和out對(duì)象
    104??*/

    105??
    106??public?CreateThread(Socket?socket)
    107??{
    108???try
    109???{
    110????s=socket;
    111????in=new?BufferedReader(new?InputStreamReader(s.getInputStream(),"gb2312"));
    112
    113????out=new?PrintWriter(s.getOutputStream(),true);
    114
    115????start();??//開新線程執(zhí)行run方法
    116
    117???}
    catch(Exception?e)
    118???{
    119????System.out.println(e);
    120???}

    121???
    122??}

    123??
    124??/*
    125??*線程方法,處理socket傳遞過來的數(shù)據(jù)
    126??*/

    127??
    128??public?void?run()
    129??{
    130???try
    131???{
    132????String?msg=in.readLine();
    133????System.out.println(msg);
    134????s.close();
    135???}
    catch(Exception?e)
    136???{
    137????System.out.println(e);
    138???}

    139??}

    140?}

    141
    142


    ??將我們剛才生成的證書放到程序所在的目錄下,上面的代碼就可以在編譯之后執(zhí)行:

    ?java?org.ec107.ssl.SSLServer

    ?在8266端口等待連接…

    ?三、?客戶端

    ?客戶端的代碼相對(duì)簡單,我們可以不在程序中指定SSL環(huán)境,而是在執(zhí)行客戶端程序時(shí)指定。需要注意的是客戶端并沒有導(dǎo)入證書,而是采用了默認(rèn)的工廠方法構(gòu)造SSLSocket:

    ?●?SSLSocketFactory?factory=(SSLSocketFactory)SSLSocketFactory.getDefault();

    ?構(gòu)造默認(rèn)的工廠方法

    ?●Socket?s=factory.createSocket("localhost",port);

    ?打開一個(gè)SSLSocket連接

    ?

    /*
    ?*SSL?Socket?的客戶端
    ?*@Author?Bromon
    ?
    */


    ?
    package?org.ec107.ssl;

    ?
    import?java.net.*;
    ?
    import?javax.net.ssl.*;
    ?
    import?javax.net.*;
    ?
    import?java.io.*;

    ?
    public?class?SSLClient
    ?
    {
    ??
    static?int?port=8266;
    ??
    public?static?void?main(String?args[])
    ??
    {
    ???
    try
    ???
    {
    ????SSLSocketFactory?factory
    =(SSLSocketFactory)SSLSocketFactory.getDefault();

    ????Socket?s
    =factory.createSocket("localhost",port);
    ????
    ????PrintWriter?out
    =new?PrintWriter(s.getOutputStream(),true);
    ????out.println(
    "安全的說你好");
    ????out.close();
    ????s.close();
    ???}
    catch(Exception?e)
    ???
    {
    ????System.out.println(e);
    ???}

    ??}

    ?}


    ?把服務(wù)器產(chǎn)生的證書(SSLKey)拷貝到程序所在的目錄,執(zhí)行這個(gè)程序的時(shí)候需要向javax.net.ssl.trustStore環(huán)境變量傳入證書名:

    ?java?–Djavax.net.ssl.trustStore=SSLKey?org.ec107.ssl.SSLClient

    ?可以在服務(wù)器的控制臺(tái)看到客戶端發(fā)送過來的數(shù)據(jù)。

    ?執(zhí)行客戶端可以有另一種方法,把證書拷貝到j(luò)ava?home/lib/security目錄下,名字改為jssecacerts,然后可以直接執(zhí)行客戶端:

    ?java?org.ec107.ssl.SSLClient

    ?程序會(huì)自動(dòng)的到上述目錄下去尋找jssecacerts文件作為默認(rèn)的證書。需要注意的是這里的java?home并不是我們在安裝J2SE時(shí)指定的那個(gè)JAVA_HOME。可以執(zhí)行一個(gè)程序來得到j(luò)ava?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,相對(duì)的,證書就應(yīng)該拷貝到C:Program?FilesJavaj2re1.4.0_02libsecurity下,如果安裝了自帶JDK的Java?IDE,比如JBuilder,情況可能會(huì)有不同。

    ???如果程序客戶在不持有證書的情況下直接進(jìn)行連接,服務(wù)器端會(huì)產(chǎn)生運(yùn)行時(shí)異常,不允許進(jìn)行連接。

    ?運(yùn)行環(huán)境:windows?2K?server,j2sdk1.4.1

    posted on 2007-03-15 21:15 黑馬_2046 閱讀(1046) 評(píng)論(0)  編輯  收藏 所屬分類: 常用代碼


    只有注冊用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲av无码专区在线播放| 天堂在线免费观看| 亚洲精品美女在线观看| 国产精品亚洲二区在线观看 | 国产成人毛片亚洲精品| 免费看的一级毛片| 麻花传媒剧在线mv免费观看| 成人黄网站片免费视频| 乱人伦中文视频在线观看免费| 一级午夜免费视频| 亚洲大成色www永久网址| 久久久久亚洲AV无码永不| 国产亚洲人成无码网在线观看| 亚洲免费在线观看| 免费**毛片在线播放直播 | 亚洲成a∧人片在线观看无码| 亚洲欧洲日本天天堂在线观看| 久久亚洲国产伦理| 亚洲色成人WWW永久网站| 精品国产日韩亚洲一区| 免费在线精品视频| 亚洲Av无码乱码在线znlu| 一区二区三区免费精品视频| 亚洲国产成人久久精品大牛影视| 亚洲人xxx日本人18| 亚洲av日韩av综合| 国产成人精品日本亚洲专| 亚洲ts人妖网站| 亚洲欧美一区二区三区日产| 亚洲一区精彩视频| 亚洲日韩乱码中文字幕| 在线综合亚洲欧洲综合网站| 77777午夜亚洲| 亚洲国产无线乱码在线观看 | 国产zzjjzzjj视频全免费| 国产成人涩涩涩视频在线观看免费 | 国产免费久久精品99re丫y| 午夜福利不卡片在线播放免费| 免费高清A级毛片在线播放| 亚洲黄色中文字幕| 不卡精品国产_亚洲人成在线|