自從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
爲測試方便,咱們可使用 CertificateCreator 製做一個用於本地測試的數字證書。code
運行 CertificateCreator.exe, 而後輸入Common Name(好比Test)、密碼、保存路徑(好比D:\server.pfx),咱們就能夠獲得包含私鑰的證書server.pfx 。雙擊server.pfx ,便可安裝證書。
在服務端RapidServerEngine初始化以前,添加以下代碼設置其 WssOptions 屬性:
WssOptions wssOptions = new WssOptions( new X509Certificate2("D:\\server.pfx", "password") ,SslProtocols.Default ,false); rapidServerEngine.WssOptions = wssOptions;
設置完成後,啓動服務端。
因爲上述生成的數字證書僅僅是用於測試的,而是不被正式承認的,因此,須要在瀏覽器設置中,將目標數字證書加入到信任列表。
好比,在360瀏覽器中,可以下設置:
在FireFox中,設置以下:
將服務器的地址(https://127.0.0.1:4530)添加到例外中。
打開入門demo的Web端源碼中的index.js文件,找到engine的Initialize方法,將 useWss 參數由false修改成true。
而後將Web端的 index.html 文件拖入瀏覽器中運行便可。
登陸一個wss客戶端,一個ws客戶端和一個.NET客戶端,服務端的UI顯示以下:
下載 Demo源碼 。