Jack Jiang

          我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
          posts - 499, comments - 13, trackbacks - 0, articles - 1

          1、引言

          隨著瓜子二手車相關業務的發展,公司有多個業務線都接入了IM系統,IM系統中的Socket長連接的安全問題變得越來越重要。本次分享正是基于此次解決Socket長連接身份安全認證的實踐總結而來,方案可能并不完美,但愿能起到拋磚引玉的作用,希望能給您的IM系統開發帶來啟發。

          學習交流:

          - 即時通訊/推送技術開發交流4群:101279154[推薦]

          - 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM

          (本文同步發布于:http://www.52im.net/thread-2106-1-1.html

          2、原作者

          封宇:瓜子二手車技術專家,中國計算機學會專業會員。主要負責瓜子即時消息解決方案及相關系統研發工作。曾供職于58同城、華北計算技術研究所,參與到家消息系統、58爬蟲系統以及多個國家級軍工科研項目的架構及研發工作。

          封宇同時還分享了其它IM方面的技術實踐和總結,您可能也會感興趣:

          從零開始搭建瓜子二手車IM系統(PPT) [附件下載]

          一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)

          一個低成本確保IM消息時序的方法探討

          移動端IM中大規模群消息的推送如何保證效率、實時性?

          3、系列文章

          本文是IM通訊安全知識系列文章中的第7篇,總目錄如下:

          即時通訊安全篇(一):正確地理解和使用Android端加密算法

          即時通訊安全篇(二):探討組合加密算法在IM中的應用

          即時通訊安全篇(三):常用加解密算法與通訊安全講解

          即時通訊安全篇(四):實例分析Android中密鑰硬編碼的風險

          即時通訊安全篇(五):對稱加密技術在Android上的應用實踐

          即時通訊安全篇(六):非對稱加密技術的原理與應用實踐

          即時通訊安全篇(七):用JWT技術解決IM系統Socket長連接的身份認證痛點》(本文)

          4、我們面臨的技術痛點

          針對我們IM系統中的Socket長連接的身份認證安全問題,瓜子有統一登錄認證系統SSO(即單點登陸系統,原理詳見《IM開發基礎知識補課(一):正確理解前置HTTP SSO單點登陸接口的原理》)。

          我們的IM長連接通道也利用這個系統做安全認證,結構如下圖:

          如上圖所示,整個認證步驟如下:

          1)用戶登錄App,App從業務后臺拿到單點登陸系統SSO頒發的token;

          2)當App需要使用IM功能時,將token傳給IM客服端SDK;

          3)客服端SDK跟IM Server建立長連接的時候用token進行認證;

          4)IM Server請求SSO單點登陸系統,確認token合法性。

          * 補充:如您對SSO單點登陸系統的了解知之甚少,請務必先閱讀《IM開發基礎知識補課(一):正確理解前置HTTP SSO單點登陸接口的原理》。

          咋一看,這個過程沒有什么問題,但是IM(尤其是移動端IM)業務的特殊性,這個流程結構并不好。

          為什么說上面的流程結構對于移動端的IM來說并不好呢?原因如下:

          1)網絡不穩定:手機(移動端)的網絡很不穩定,進出地鐵可能斷網,挪動位置也可能換基站;

          2)長連接頻繁建立和釋放:正因為1)中的原因,在一個聊天會話過程中,會經常重新建立長連接,從而導致上圖里的第3步會被頻繁執行,進而第4步也會頻繁執行;

          3)系統壓力會增大:鑒于2)中的表現,將大大增加了SSO單點登陸系統的壓力(因為IM實例需要頻繁的調用SSO系統,從而完全客戶端長連接的身份合法性檢查);

          4)用戶體驗也不好:長連接建立過程中,因SSO單點登陸系統并不屬于IM服務端實例范圍之內,IM服務端實例與SSO系統的通信等,帶來的額外通信鏈路延遲對于用戶的體驗也是一種傷害(而且SSO系統也可能短暫開小差)。

          如果不通過上圖中的第4步就能完成IM長連接的身份合法性驗證,那這個痛點會得到極大緩解。于是,我們便想到了JWT技術。

          * 題外話:如果您對移動端弱網絡的物理特性還不了解,那么下面的文章有助于您建立起這方面的認知:

          現代移動端網絡短連接的優化手段總結:請求速度、弱網適應、安全保障

          移動端IM開發者必讀(一):通俗易懂,理解移動網絡的“弱”和“慢”

          移動端IM開發者必讀(二):史上最全移動弱網絡優化方法總結

          5、完全搞懂什么是JWT技術

          5.1 基礎知識

          JSON Web Token(簡稱JWT),是一個開放安全的行業標準(詳見RFC7519),可以用于多個系統之間傳遞安全可靠的信息(也包括本文中將要用到的傳遞身份認證信息的場景)。

          一個完整的JWT的token字符串是什么樣子的結構?

          ▲ JWT說到底也是一個token字符串,它由三部分組成:頭部、載荷與簽名

          正如上圖中所示,一個JWT的token字符串組成如下:

          1)紅色的為Header:指定token類型與簽名類型;

          2)紫色的為載荷(playload):存儲用戶id等關鍵信息;

          3)藍色的為簽名:保證整個信息的完整性、可靠性(這個簽名字符串,相當于是一段被加密了的密文文本,安全性就是由它來決定的)。

          5.2解密JWT的頭部(Header)

          JWT的頭部用于描述關于該JWT的最基本的信息,例如其類型以及簽名所用的算法等。

          這可以被表示成一個JSON對象:

          {

          "typ": "JWT",

          "alg": "HS256"

          }

          ▲ 在這個頭信息里,標明了這是一個JWT字符串,并且所用的簽名算法是HS256算法

          對它進行Base64編碼,之后的字符串就成了JWT的Header(頭部),也就是你在5.1節中看到的紅色部分:

          eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

          (你可以自已試著進行Base64的加密和解決,比如用這個在線工具:http://tool.oschina.net/encrypt?type=3

          5.3 解密JWT的載荷(playload)

          在載荷(playload)中可以定義以下屬性:

          1)iss: 該JWT的簽發者;

          2)sub: 該JWT所面向的用戶;

          3)aud: 接收該JWT的一方;

          4)exp(expires): 什么時候過期,這里是一個Unix時間戳;

          5)iat(issued at): 在什么時候簽發的。

          上面的信息也可以用一個JSON對象來描述,將上面的JSON對象進行base64編碼,可以得到下面的字符串。

          這個字符串我們將它稱作JWT的Payload(載荷),以下字串樣例就是你在5.1節中看到的紫色部分:

          eyJpc3MiOiIyOWZmMDE5OGJlOGM0YzNlYTZlZTA4YjE1MGRhNTU0NC1XRUIiLCJleHAiOjE1MjI0OTE5MTV9

          (你可以自已試著進行Base64的加密和解決,比如用這個在線工具:http://tool.oschina.net/encrypt?type=3

          5.4 解決JWT的簽名(Signature)

          JWT的簽名部分,在官方文檔中是如下描述的:

          HMACSHA256(

          base64UrlEncode(header) + "." +

          base64UrlEncode(payload),

          secret)

          上述偽碼的意義,即如下操作:

          eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIyOWZmMDE5OGJlOGM0YzNlYTZlZTA4YjE1MGRhNTU0NC1XRUIiLCJleHAiOjE1MjI0OTE5MTV9

          ▲ 將上面的兩個base64編碼后的字符串都用句號‘.’連接在一起(頭部在前),就形成了如下字符串

          最后,我們將上面拼接完的字符串用HS256算法進行加密。在加密的時候,我們還需要提供一個密鑰(secret)。

          那么,按照RFC7519上描述的方法,就可以得到我們加密后的內容:

          P-k-vIzxElzyzFbzR4tUxAAET8xT9EP49b7hpcPazd0

          ▲ 這個就是我們需要的JWT的簽名部分了

          5.5 簽名的目的

          生成JWT的token字符串的最后一步簽名過程,實際上是對頭部以及載荷內容進行加密。

          一般而言:加密算法對于不同的輸入產生的輸出總是不一樣的。所以,如果有人對頭部以及載荷的內容解碼之后進行修改,再進行編碼的話,那么新的頭部和載荷的簽名和之前的簽名就將是不一樣的。而且,如果不知道服務器加密的時候用的密鑰的話,得出來的簽名也一定會是不一樣的。

          換句話說:你的JWT字符串的安全強度,基本上就是由這個簽名部分來決定的。

          使用時:服務器端在接受到JWT的token字符串后,會首先用開發者指明的secret(可以理解為密碼)對頭部和載荷的內容用同一算法再次簽名。那么服務器應用是怎么知道我們用的是哪一種算法呢?別忘了,我們在JWT的頭部中已經用alg字段指明了我們的加密算法了。

          如果服務器端對頭部和載荷再次以同樣方法簽名之后發現,自己計算出來的簽名和接受到的簽名不一樣,那么就說明這個Token的內容被別人動過的,我們應該拒絕這個JWT Token,返回一個HTTP 401 Unauthorized響應。

          5.6 一個典型的JWT應用流程

          JWT是一個怎樣的流程? 先上個官方文檔的圖:

          如上圖所示,整個應用流程描述如下:

          1)客戶端使用賬戶密碼請求登錄接口;

          2)登錄成功后服務器使用簽名密鑰生成JWT ,然后返回JWT給客戶端;

          3)客戶端再次向服務端請求其他接口時帶上JWT;

          4)服務端接收到JWT后驗證簽名的有效性.對客戶端做出相應的響應。

          5.7 總而言之

          JWT的整個技術原理,就是一個很典型的對稱加密應用過程,通俗的說也就是用開發者在服務端保存的密碼,對用戶的id等信息進行加密并按照JWT的規則(見5.1節)組成字符串返回給用戶。用戶在使用時將這個字符串提交給對應的服務端,服務端取出JWT字串的頭信息、載荷,用開發者指明的密碼試著進行加密并得到一個字符串(即合法的JWT token),兩相比較,相同則認為用戶提交上來的JWT合法,否則不合法。這就是JWT的全部原理,相當簡單易懂。

          JWT技術的價值不在于具體的技術實現,而在于它的思想本身,尤其在異構系統、分布式系統方面,可以極大的簡化安全認證的成本,包括簡化架構復雜性、降低使用門檻等,因為JWT的技術原理決定了認證的過程不需要其它系統的參與,由當前實例自已就可以完成,而成認證代碼極小(就是一個加密字符串的比較而已)。

          它的技術思路在當前的各種開發系統中應用廣泛,比如下圖中微信公眾號的服務接口配置里,也用到了類似的思想:

          另外,蘋果著名的APNs推送服務,也支持JWT技術,詳見《基于APNs最新HTTP/2接口實現iOS的高性能消息推送(服務端篇)》第6.2節:

          ▲ 上述截圖內容摘錄自蘋果官方開發者文檔

          6、我們是怎樣使用JWT技術的?

          上一章節,我們詳細理解了JWT技術的原理,那么回到本文的初衷:我們該如何使用JWT技術來解決上面所提到的通點呢?

          我們采用JWT驗證IM的Socket長連接流程如下:

          如上圖所示,整個驗證過程描述如下:

          1)用戶登錄App(使用IM客服端SDK),App從業務后臺拿到SSO單點登陸系統頒發的token(注意:此token還不是JWT的token,它將在第3)步中被使用并生成真正的JWT token);

          2)當App需要使用IM功能時,將token傳給IM客服端SDK(這是在客戶端完成的,即當App的功能調用IM客服端SDK時傳入);

          3)IM客服端SDK將用戶名及第2步中得到的token發給后臺的JWT Server(簽發JWT token的模塊),請求JWT token;

          4)收到第3)步中提交過來的token后,JWT Server會通過RPC等技術向SSO系統提交驗證此token的合法性,如果合法,將用跟IM Server約定的Secret(你可以理解為這就是一個固定的密碼而已),根據業務需要簽發JWT token,并最終返回給IM客服端SDK(即完成第3步中的請求)。

          5)后緒,IM客服端SDK將使用得到的JWT token請求IM Server驗證長連接,IM Server根據約定的算法(不依賴其他系統直接用JWT的規則,加上第4)步中與JWT Server 約定的Secret)即可完成jwttoken合法性驗證。

          通過上述努力,移動端在弱網情況下的頻繁建立長連接的身份驗證痛點得到了解決。

          7、JWT技術的缺點

          當然,我們之所以選擇JWT技術,主要看重的還是它簡單易用,但或許正因為如此,某種程度上來說這也恰是居致它的缺點的原因所在。

          JWT技術的缺點及建議的解決方法主要有:

          1)JWT的最大缺點是服務器不保存會話狀態,所以在使用期間不可能取消token或更改token的權限。也就是說,一旦JWT簽發,在有效期內將會一直有效;

          2)JWT本身包含認證信息(即你在第5.1節中看到的頭信息、負載信息),因此一旦信息泄露,任何人都可以獲得token的所有權限。為了減少盜用,JWT的有效期不宜設置太長。對于某些重要操作,用戶在使用時應該每次都進行進行身份驗證;

          3)為了減少盜用和竊取,JWT不建議使用HTTP協議來傳輸代碼,而是使用加密的HTTPS(SSL)協議進行傳輸。

          以下這篇文章列了一些適用JWT的應用場景,僅供參考:

          https://www.jianshu.com/p/af8360b83a9f

          8、點評

          JWT其實是一項比較有爭議的技術,夸它的人會說它簡單易用、成本低,極度貶低它的人會說它的安全性就像一層窗戶紙——捅一下就破了。

          不可否認,跟當前流行的非對稱加密技術(大家最熟悉的HTTPS協議就是一個典型的非對稱加密應用場景)相比,JWT技術的安全系數確實相對要低一些,因為JWT技術的本質就是對稱加密技術的應用,而非對稱加密技術出現的原因也就是為了提升對稱加密技術所不具有的一些安全性。

          但非對稱加密技術這么好,也并不意味著對稱加密技術就一無是處,因為并不是所有場景都需要用性能、架構的復雜性、運維成本來換取高安全性,還是那句話:“安全這東西,夠用就行”,而這也正是JWT這種技術仍然有其價值的原因所在。

          非對稱加密技術雖然安全,但也并非理論上的無懈可擊,這世上還沒有絕對安全的算法,總之,不苛責級極致安全的情況下,夠用便好,你說呢?

          如果您對對稱加密和非對稱加密技術的還不是太了解,可以閱讀以下文章:

          即時通訊安全篇(三):常用加解密算法與通訊安全講解

          即時通訊安全篇(六):非對稱加密技術的原理與應用實踐

          附錄:更多即時通訊方面的文章

          如果您是IM開發初學者,強烈建議首先閱讀:

          新手入門一篇就夠:從零開發移動端IM

          即時通訊安全方面的文章匯總如下:

          即時通訊安全篇(一):正確地理解和使用Android端加密算法

          即時通訊安全篇(二):探討組合加密算法在IM中的應用

          即時通訊安全篇(三):常用加解密算法與通訊安全講解

          即時通訊安全篇(四):實例分析Android中密鑰硬編碼的風險

          即時通訊安全篇(五):對稱加密技術在Android平臺上的應用實踐

          即時通訊安全篇(六):非對稱加密技術的原理與應用實踐

          即時通訊安全篇(七):用JWT技術解決IM系統Socket長連接的身份認證痛點

          傳輸層安全協議SSL/TLS的Java平臺實現簡介和Demo演示

          理論聯系實際:一套典型的IM通信協議設計詳解(含安全層設計)

          微信新一代通信安全解決方案:基于TLS1.3的MMTLS詳解

          來自阿里OpenIM:打造安全可靠即時通訊服務的技術實踐分享

          簡述實時音視頻聊天中端到端加密(E2EE)的工作原理

          移動端安全通信的利器——端到端加密(E2EE)技術詳解

          Web端即時通訊安全:跨站點WebSocket劫持漏洞詳解(含示例代碼)

          通俗易懂:一篇掌握即時通訊的消息傳輸安全原理

          IM開發基礎知識補課(四):正確理解HTTP短連接中的Cookie、Session和Token

          快速讀懂量子通信、量子加密技術

          即時通訊安全篇(七):如果這樣來理解HTTPS原理,一篇就夠了

          一分鐘理解 HTTPS 到底解決了什么問題

          >> 更多同類文章 ……

          (本文同步發布于:http://www.52im.net/thread-2106-1-1.html



          作者:Jack Jiang (點擊作者姓名進入Github)
          出處:http://www.52im.net/space-uid-1.html
          交流:歡迎加入即時通訊開發交流群 215891622
          討論:http://www.52im.net/
          Jack Jiang同時是【原創Java Swing外觀工程BeautyEye】【輕量級移動端即時通訊框架MobileIMSDK】的作者,可前往下載交流。
          本博文 歡迎轉載,轉載請注明出處(也可前往 我的52im.net 找到我)。


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


          網站導航:
           
          Jack Jiang的 Mail: jb2011@163.com, 聯系QQ: 413980957, 微信: hellojackjiang
          主站蜘蛛池模板: 嵩明县| 西贡区| 天长市| 郁南县| 石渠县| 南靖县| 毕节市| 西乌珠穆沁旗| 曲靖市| 阿图什市| 渝中区| 古交市| 定远县| 靖宇县| 安吉县| 蛟河市| 桂东县| 遂平县| 衢州市| 乌鲁木齐县| 吐鲁番市| 英超| 息烽县| 嘉善县| 舟曲县| 金塔县| 丹阳市| 岚皋县| 宁津县| 彭水| 昌邑市| 牟定县| 佛教| 东港市| 沂南县| 西峡县| 德格县| 达尔| 嘉黎县| 武鸣县| 北海市|