如何讓服務端同時支持WebSocket和SSL加密的WebSocket(即同時支持ws和wss)?

  自從HTML5出來之後,使用WebSocket通訊就變得火熱起來,基於WebSocket開發的手機APP和手機遊戲也愈來愈多。個人一些開發APP的朋友,開始使用WebSocket通訊,後來以爲通訊不夠安全,想要對通訊進行加密,因而天然而然地就想從ws升級到wss。在升級的過程當中,就會存在舊的ws客戶端與新的wss客戶端同時鏈接到同一個服務器的狀況。因此,若是同一個服務端,能同時支持ws和wss,那就太方便了。html

一. 實現方案

  可是,要服務端同時支持ws與wss並不太容易,其難點主要在於:wss通道必須在TCP鏈接剛創建時(收發消息前)就要先進行SSL加密,不然,後續的通訊將沒法正常進行。如此一來,當同時存在ws和wss客戶端時,服務器在還沒有通訊以前就沒法具體分辨哪一個是ws哪一個是wss。那怎麼辦了?咱們的解決方案,是採用試探法,該方案已經在 ESFramework 通訊框架中實現。 api

(1)因爲wss通道必須在TCP鏈接剛創建時(收發消息前)就要先進行SSL加密,不然,後續的通訊將沒法正常進行。瀏覽器

(2)基於(1),在沒有收發任何消息時,服務端就沒法將wss客戶端與其它客戶端區分開來。安全

(3)爲此採用的辦法是:對於任何剛創建的TCP鏈接,先都不加密它,等收到的第一個消息來判斷其消息的頭標誌。服務器

(4)若是頭標誌不是ESFramework所規定的標誌,則表示這第一個消息是密文,沒法被解析,從而說明這個客戶端是wss。因而將該客戶端的ip放到cache中,並斷開該鏈接。框架

(5)wss客戶端會從新連上來,此時服務端從cache中發現已經存在目標ip,則斷定其爲wss客戶端,因而當即使用SSL加密該通道,以後,該wss客戶端就能夠正常通訊了。測試

(6)因爲wss 客戶端 IP在cache中的過時時間是 6秒左右,因此,若是一個客戶端IP剛登陸了wss客戶端,那麼在同一個IP上登陸第二個客戶端(任何客戶端類型),就須要相隔6秒以後。加密

   基於以上方案實現服務端後,咱們接下來基於 ESFramework入門demo 來具體講解一下如何在實際應用中同時支持ws和wss。spa

二. 服務端實現

1. 數字證書

      爲測試方便,咱們可使用 CertificateCreator 製做一個用於本地測試的數字證書。code

      運行 CertificateCreator.exe, 而後輸入Common Name(好比Test)、密碼、保存路徑(好比D:\server.pfx),咱們就能夠獲得包含私鑰的證書server.pfx 。雙擊server.pfx ,便可安裝證書。 

2. 服務端引擎設置

       在服務端RapidServerEngine初始化以前,添加以下代碼設置其 WssOptions 屬性:

        WssOptions wssOptions = new WssOptions( new X509Certificate2("D:\\server.pfx", "password") ,SslProtocols.Default ,false);
        rapidServerEngine.WssOptions = wssOptions;   

        設置完成後,啓動服務端。 

三. 客戶端實現

1. 信任測試用的數字證書      

        因爲上述生成的數字證書僅僅是用於測試的,而是不被正式承認的,因此,須要在瀏覽器設置中,將目標數字證書加入到信任列表。

        好比,在360瀏覽器中,可以下設置:

          

        在FireFox中,設置以下:

         

          將服務器的地址(https://127.0.0.1:4530)添加到例外中。  

2. 客戶端引擎設置

        打開入門demo的Web端源碼中的index.js文件,找到engine的Initialize方法,將 useWss 參數由false修改成true。

        而後將Web端的 index.html 文件拖入瀏覽器中運行便可。 

四. 運行效果

       登陸一個wss客戶端,一個ws客戶端和一個.NET客戶端,服務端的UI顯示以下:

       

        下載 Demo源碼

相關文章
相關標籤/搜索