用JWT技術解決IM系統Socket長鏈接的身份認證痛點

一、引言

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

學習交流:html

- 即時通信/推送技術開發交流4羣:101279154[推薦]算法

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

(本文同步發佈於:http://www.52im.net/thread-2106-1-1.html服務器

二、原做者

 

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

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

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

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

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

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

三、系列文章

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

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

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

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

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

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

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

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

四、咱們面臨的技術痛點

針對咱們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開發者必讀(二):史上最全移動弱網絡優化方法總結

五、徹底搞懂什麼是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節:

 

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

六、咱們是怎樣使用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合法性驗證。

經過上述努力,移動端在弱網狀況下的頻繁創建長鏈接的身份驗證痛點獲得瞭解決。

七、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

八、點評

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

相關文章
相關標籤/搜索