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

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

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

    隨筆 - 5, 文章 - 0, 評論 - 1, 引用 - 0
    數據加載中……

    使用SSL構建安全的Socket(轉)

    bromon原創?版權所有

    ?SSL(安全套接層)是Netscape公司在1994年開發的,最初用于WEB瀏覽器,為瀏覽器與服務器間的數據傳遞提供安全保障,提供了加密、來源認證和數據完整性的功能。現在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的安全性。

    ?完整代碼如下:

    ??1/*
    ??2?*SSL?Socket的服務器端
    ??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;??//系統將要監聽的端口號,82.6.6是偶以前女朋友的生日^_^
    ?16??static?SSLServerSocket?server;
    ?17??
    ?18??/*
    ?19??*構造函數
    ?20??*/

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

    ?26??
    ?27??
    ?28??/*
    ?29??*@param?port?監聽的端口號
    ?30??*@return?返回一個SSLServerSocket對象
    ?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");??//創建JKS密鑰庫
    ?45
    ?46????ks.load(new?FileInputStream(key),keyStorePass);
    ?47
    ?48????//創建管理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????//根據上面配置的SSL上下文來產生SSLServerSocketFactory,與通常的產生方法不同
    ?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對象處理,主線程繼續監聽
    ?82?????new?CreateThread(socket);
    ?83?????
    ?84????}

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

    ?89??}

    ?90?}

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

    ?95
    ?96?class?CreateThread?extends?Thread
    ?97?{
    ?98??static?BufferedReader?in;
    ?99??static?PrintWriter?out;
    100??static?Socket?s;
    101??
    102??/*
    103??*構造函數,獲得socket連接,初始化in和out對象
    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();??//開新線程執行run方法
    116
    117???}
    catch(Exception?e)
    118???{
    119????System.out.println(e);
    120???}

    121???
    122??}

    123??
    124??/*
    125??*線程方法,處理socket傳遞過來的數據
    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


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

    ?java?org.ec107.ssl.SSLServer

    ?在8266端口等待連接…

    ?三、?客戶端

    ?客戶端的代碼相對簡單,我們可以不在程序中指定SSL環境,而是在執行客戶端程序時指定。需要注意的是客戶端并沒有導入證書,而是采用了默認的工廠方法構造SSLSocket:

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

    ?構造默認的工廠方法

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

    ?打開一個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);
    ???}

    ??}

    ?}


    ?把服務器產生的證書(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 閱讀(1045) 評論(0)  編輯  收藏 所屬分類: 常用代碼


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 久久亚洲精品中文字幕| 亚洲国产精品成人综合色在线婷婷| 黄色网址免费在线观看| 亚洲另类激情综合偷自拍| 成人特黄a级毛片免费视频| 污污污视频在线免费观看| 亚洲视频小说图片| 日本人的色道www免费一区| 成人精品一区二区三区不卡免费看| 亚洲中文无码a∨在线观看| 亚洲国产成人久久综合一区77 | 深夜A级毛片视频免费| 亚洲AV无码久久精品成人| 毛片免费视频播放| a级毛片免费在线观看| 亚洲av产在线精品亚洲第一站| 亚洲国产中文v高清在线观看| 免费视频爱爱太爽了| 一区二区三区免费在线观看| 久久精品国产亚洲AV蜜臀色欲| 亚洲精品视频在线看| 免费看片A级毛片免费看| 久久精品国产免费一区| 亚洲av无码片vr一区二区三区| 亚洲综合久久综合激情久久| 亚洲国产成人精品久久久国产成人一区二区三区综| 99re6免费视频| 国产久爱免费精品视频 | 二个人看的www免费视频| 亚洲中文字幕乱码熟女在线| 久久精品国产亚洲AV麻豆不卡| 日韩视频免费在线| 国产成人午夜精品免费视频| 免费无码又爽又刺激高潮软件| 日韩亚洲翔田千里在线| 亚洲国产成人久久| 亚洲今日精彩视频| 国产日韩亚洲大尺度高清| 免费99热在线观看| 国产免费久久精品久久久| 四虎成人精品一区二区免费网站|