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

jsjsjjs發表於2018-04-09

本文引用了簡書作者“騎小豬看流星”技術文章“Cookie、Session、Token那點事兒”的部分內容,感謝原作者。

1、前言

眾所周之,IM是個典型的快速資料流交換系統,當今主流IM系統(尤其移動端IM)的資料流交換方式都是Http短連線+TCP或UDP長連線來實現。Http短連線主要用於從伺服器讀取各種持久化資訊:比如使用者資訊、聊天曆史記錄、好友列表等等,長連線則是用於實時的聊天訊息或指令的接收和傳送。

作為IM系統中不可或缺的技術,Http短連的重要性無可替代,但Http作為傳統網際網路資訊交換技術,一些典型的概念比如:Cookie、Session、Token,對於IM新手程式設計師來說並不容易理解。鑑於Http短連線在IM系統中的重要性,如何正確地理解Cookie、Session、Token這樣的東西,決定了您的技術方案能否找到最佳實踐。本文將從基礎上講解這3者的原理、用途以及正確地應用場景。

題外話:本文討論的使用Http短連線的話題可能並不適用於微信這樣的IM,因為微信的短連線並非使用Http標準協議實現,而是基於自研的Mars網路層框架再造了一套短連線機制,從而更適用於IM這種場景(更低延遲、更省流量、更好的弱網適應演算法等),詳情請見《如約而至:微信自用的移動端IM網路層跨平臺元件庫Mars已正式開源》。當然,Mars雖好,但不一定適合您的團隊,因為定製的方案相較於標準通用方案來說,沒有強大的技術實力,還是不太容易掌控的了的。

一篇文章:現代移動端網路短連線的優化手段總結:請求速度、弱網適應、安全保障》這篇文章詳述了現今行動網路下http短連線的網路層技術問題,有助於更好地理解本文,有興趣的話也推薦讀一讀。

學習交流:

– 即時通訊開發交流群:320837163[推薦]

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

(本文同步釋出於:http://www.52im.net/thread-1525-1-1.html

2、系列文章

▼ IM開發乾貨系列文章(本文是其第13篇):

IM訊息送達保證機制實現(一):保證線上實時訊息的可靠投遞

IM訊息送達保證機制實現(二):保證離線訊息的可靠投遞

如何保證IM實時訊息的“時序性”與“一致性”?

IM單聊和群聊中的線上狀態同步應該用“推”還是“拉”?

IM群聊訊息如此複雜,如何保證不丟不重?

一種Android端IM智慧心跳演算法的設計與實現探討(含樣例程式碼)

移動端IM登入時拉取資料如何作到省流量?

通俗易懂:基於叢集的移動端IM接入層負載均衡方案分享

淺談移動端IM的多點登陸和訊息漫遊原理

IM開發基礎知識補課(一):正確理解前置HTTP SSO單點登陸介面的原理

IM開發基礎知識補課(二):如何設計大量圖片檔案的服務端儲存架構?

IM開發基礎知識補課(三):快速理解服務端資料庫讀寫分離原理及實踐建議

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

如果您是IM開發初學者,強烈建議首先閱讀《新手入門一篇就夠:從零開發移動端IM》。

3、什麼是Cookie?

Cookie 技術產生源於 HTTP 協議在網際網路上的急速發展。隨著網際網路時代的策馬奔騰,頻寬等限制不存在了,人們需要更復雜的網際網路互動活動,就必須同伺服器保持活動狀態(簡稱:保活)。於是,在瀏覽器發展初期,為了適應使用者的需求技術上推出了各種保持 Web 瀏覽狀態的手段,其中就包括了 Cookie 技術。Cookie 在計算機中是個儲存在瀏覽器目錄中的文字檔案,當瀏覽器執行時,儲存在 RAM 中發揮作用 (此種 Cookies 稱作 Session Cookies),一旦使用者從該網站或伺服器退出,Cookie 可儲存在使用者本地的硬碟上 (此種 Cookies 稱作 Persistent Cookies)。

Cookie 起源:1993 年,網景公司僱員 Lou Montulli 為了讓使用者在訪問某網站時,進一步提高訪問速度,同時也為了進一步實現個人化網路,發明了今天廣泛使用的 Cookie。(所以,適當的偷懶也會促進人類計算機發展史的一小步~)

Cookie時效性:目前有些 Cookie 是臨時的,有些則是持續的。臨時的 Cookie 只在瀏覽器上儲存一段規定的時間,一旦超過規定的時間,該 Cookie 就會被系統清除。

Cookie使用限制:Cookie 必須在 HTML 檔案的內容輸出之前設定;不同的瀏覽器 (Netscape Navigator、Internet Explorer) 對 Cookie 的處理不一致,使用時一定要考慮;客戶端使用者如果設定禁止 Cookie,則 Cookie 不能建立。 並且在客戶端,一個瀏覽器能建立的 Cookie 數量最多為 300 個,並且每個不能超過 4KB,每個 Web 站點能設定的 Cookie 總數不能超過 20 個。

執行流程:

A:首先,客戶端會傳送一個http請求到伺服器端;

B: 伺服器端接受客戶端請求後,傳送一個http響應到客戶端,這個響應頭,其中就包含Set-Cookie頭部;

C:在客戶端發起的第二次請求(注意:如果伺服器需要我們帶上Cookie,我們就需要在B步驟上面拿到這個Cookie然後作為請求頭一起發起第二次請求),提供給了伺服器端可以用來唯一標識客戶端身份的資訊。這時,伺服器端也就可以判斷客戶端是否啟用了cookies。儘管,使用者可能在和應用程式互動的過程中突然禁用cookies的使用,但是,這個情況基本是不太可能發生的,所以可以不加以考慮,這在實踐中也被證明是對的。

為了方便理解,可以先看下這張流程執行圖加深概念:

那麼,在瀏覽器上面的請求頭和Cookie在那?下圖給大家擷取了其中一種:

4、Cookie 和 Session

眾所周知,HTTP 是一個無狀態協議,所以客戶端每次發出請求時,下一次請求無法得知上一次請求所包含的狀態資料,如何能把一個使用者的狀態資料關聯起來呢?

比如在淘寶的某個頁面中,你進行了登陸操作。當你跳轉到商品頁時,服務端如何知道你是已經登陸的狀態?

5、關於Session

Cookie 雖然很方便,但是使用 Cookie 有一個很大的弊端,Cookie 中的所有資料在客戶端就可以被修改,資料非常容易被偽造,那麼一些重要的資料就不能存放在 Cookie 中了,而且如果 Cookie 中資料欄位太多會影響傳輸效率。為了解決這些問題,就產生了 Session,Session 中的資料是保留在伺服器端的。

總之:Session是對於服務端來說的,客戶端是沒有Session一說的。Session是伺服器在和客戶端建立連線時新增客戶端連線標誌,最終會在伺服器軟體(Apache、Tomcat、JBoss)轉化為一個臨時Cookie傳送給給客戶端,當客戶端第一請求時伺服器會檢查是否攜帶了這個Session(臨時Cookie),如果沒有則會新增Session,如果有就拿出這個Session來做相關操作。

Session 的運作通過一個session_id來進行。session_id通常是存放在客戶端的 Cookie 中,比如在 express 中(說的是Nodejs),預設是connect.sid這個欄位,當請求到來時,服務端檢查 Cookie 中儲存的 session_id 並通過這個 session_id 與伺服器端的 Session data 關聯起來,進行資料的儲存和修改。

這意思就是說,當你瀏覽一個網頁時,服務端隨機產生一個 1024 位元長的字串,然後存在你 Cookie 中的connect.sid欄位中。當你下次訪問時,Cookie 會帶有這個字串,然後瀏覽器就知道你是上次訪問過的某某某,然後從伺服器的儲存中取出上次記錄在你身上的資料。由於字串是隨機產生的,而且位數足夠多,所以也不擔心有人能夠偽造。偽造成功的概率比坐在家裡程式設計時被鄰居家的狗突然闖入並咬死的機率還低。

一個完整的Cookie+Session應用過程如下圖所示:

Session 可以存放在:

1)記憶體;

2)Cookie本身;

3)redis 或 memcached 等快取中;

4)資料庫中。

線上來說,快取的方案比較常見,存資料庫的話,查詢效率相比前三者都太低,不推薦;Cookie Session 有安全性問題,下面會提到。

傳統的身份驗證方法從最早的Cookie到Session以及給Session Cookie做個加密,接下來我們來看看Token認證。

6、什麼是Token?

6.1 Token的起源

諸如Ember,Angular,Backbone之類的Web前端框架類庫正隨著更加精細的Web應用而日益壯大。正因如此,伺服器端的組建也正正在從傳統的任務中解脫,轉而變的更像API。API使得傳統的前端和後端的概念解耦。開發者可以脫離前端,獨立的開發後端,在測試上獲得更大的便利。這種途徑也使得一個移動應用和網頁應用可以使用相同的後端。

當使用一個API時,其中一個挑戰就是認證(authentication)。在傳統的web應用中,服務端成功的返回一個響應(response)依賴於兩件事。一是,他通過一種儲存機制儲存了會話資訊(Session)。每一個會話都有它獨特的資訊(id),常常是一個長的,隨機化的字串,它被用來讓未來的請求(Request)檢索資訊。其次,包含在響應頭(Header)裡面的資訊使客戶端儲存了一個Cookie。伺服器自動的在每個子請求裡面加上了會話ID,這使得伺服器可以通過檢索Session中的資訊來辨別使用者。這就是傳統的web應用逃避HTTP面向無連線的方法(This is how traditional web applications get around the fact that HTTP is stateless)。

API應該被設計成無狀態的(Stateless)。這意味著沒有登陸,登出的方法,也沒有sessions,API的設計者同樣也不能依賴Cookie,因為不能保證這些request是由瀏覽器所發出的。自然,我們需要一個新的機制。Token這種東西就應運而生了。

6.2 Token是什麼

token是使用者身份的驗證方式,我們通常叫它:令牌。最簡單的token組成:uid(使用者唯一的身份標識)、time(當前時間的時間戳)、sign(簽名,由token的前幾位+鹽以雜湊演算法壓縮成一定長的十六進位制字串,可以防止惡意第三方拼接token請求伺服器)。還可以把不變的引數也放進token,避免多次查庫。

我們可以把Token想象成一個安全的護照。你在一個安全的前臺驗證你的身份(通過你的使用者名稱和密碼),如果你成功驗證了自己,你就可以取得這個。當你走進大樓的時候(試圖從呼叫API獲取資源),你會被要求驗證你的護照,而不是在前臺重新驗證。

簡單來說,就像下圖這樣:

6.3 Token的應用場景

Token的使用流程:

A:當使用者首次登入成功(註冊也是一種可以適用的場景)之後, 伺服器端就會生成一個 token 值,這個值,會在伺服器儲存token值(儲存在資料庫中),再將這個token值返回給客戶端;

B:客戶端拿到 token 值之後,進行本地儲存。(SP儲存是大家能夠比較支援和易於理解操作的儲存);

C:當客戶端再次傳送網路請求(一般不是登入請求)的時候,就會將這個 token 值附帶到引數中傳送給伺服器;

D:伺服器接收到客戶端的請求之後,會取出token值與儲存在本地(資料庫)中的token值做對比。

Token的身份認證邏輯:

對比一:如果兩個 token 值相同, 說明使用者登入成功過!當前使用者處於登入狀態!

對比二:如果沒有這個 token 值, 則說明沒有登入成功;

對比三:如果 token 值不同: 說明原來的登入資訊已經失效,讓使用者重新登入。

6.4 Token的安全性

我們可以儲存認證過的Token記錄在伺服器上,來新增一個附加的安全層,然後在每一步驗證Token的時候驗證這個記錄(比如每次客戶端請求API時檢查這個Token的合法性)。這將會阻止第三方偽裝一個Token,也將會使得伺服器可以失效一個Token。

7、Cookie和Session的區別小結

1)cookie資料存放在客戶的瀏覽器上,session資料放在伺服器上;

2)cookie不是很安全,別人可以分析存放在本地的cookie並進行cookie欺騙,考慮到安全應當使用session;

3)session會在一定時間內儲存在伺服器上。當訪問增多,會比較佔用你伺服器的效能,考慮到減輕伺服器效能方面,應當使用cookie;

4)單個cookie儲存的資料不能超過4K,很多瀏覽器都限制一個站點最多儲存20個cookie。

所以個人建議:

將登陸資訊等重要資訊存放為session;

其他資訊如果需要保留,可以放在cookie中。

8、Token 和 Session 的區別小結

Session和 token並不矛盾,作為身份認證token安全性比Session好,因為每個請求都有簽名還能防止監聽以及重放攻擊,而Session就必須靠鏈路層來保障通訊安全了。如上所說,如果你需要實現有狀態的會話,仍然可以增加session來在伺服器端儲存一些狀態

App通常用restful api跟server打交道。Rest是stateless的,也就是app不需要像browser那樣用cookie來儲存Session,因此用Session token來標示自己就夠了,session/state由api server的邏輯處理。如果你的後端不是stateless的rest api,那麼你可能需要在app裡儲存Session.可以在app裡嵌入webkit,用一個隱藏的browser來管理cookie Session.

Session是一種HTTP儲存機制,目的是為無狀態的HTTP提供的持久機制。所謂Session認證只是簡單的把User資訊儲存到Session裡,因為SID的不可預測性,暫且認為是安全的。這是一種認證手段。而Token,如果指的是OAuth Token或類似的機制的話,提供的是 認證 和 授權 ,認證是針對使用者,授權是針對App。其目的是讓 某App有權利訪問 某使用者 的資訊。這裡的Token是唯一的。不可以轉移到其它App上,也不可以轉到其它 使用者 上。轉過來說Session。Session只提供一種簡單的認證,即有此SID,即認為有此User的全部權利。是需要嚴格保密的,這個資料應該只儲存在站方,不應該共享給其它網站或者第三方App。所以簡單來說,如果你的使用者資料可能需要和第三方共享,或者允許第三方呼叫API介面,用Token。如果永遠只是自己的網站,自己的App,用什麼就無所謂了。

Token就是令牌,比如你授權(登入)一個程式時,他就是個依據,判斷你是否已經授權該軟體;cookie就是寫在客戶端的一個txt檔案,裡面包括你登入資訊之類的,這樣你下次在登入某個網站,就會自動呼叫cookie自動登入使用者名稱;session和cookie差不多,只是Session是寫在伺服器端的檔案,也需要在客戶端寫入cookie檔案,但是檔案裡是你的瀏覽器編號。Session的狀態是儲存在伺服器端,客戶端只有Session id;而Token的狀態是儲存在客戶端。

附錄:更多IM技術文章

[1] 有關IM安全的文章:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

>> 更多同類文章 ……

[2] 有關IM架構設計的文章:

淺談IM系統的架構設計

簡述移動端IM開發的那些坑:架構設計、通訊協議和客戶端

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

一套原創分散式即時通訊(IM)系統理論架構方案

從零到卓越:京東客服即時通訊系統的技術架構演進歷程

蘑菇街即時通訊/IM伺服器開發之架構選擇

騰訊QQ1.4億線上使用者的技術挑戰和架構演進之路PPT

微信後臺基於時間序的海量資料冷熱分級架構設計實踐

微信技術總監談架構:微信之道——大道至簡(演講全文)

如何解讀《微信技術總監談架構:微信之道——大道至簡》

快速裂變:見證微信強大後臺架構從0到1的演進歷程(一)

17年的實踐:騰訊海量產品的技術方法論

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

現代IM系統中聊天訊息的同步和儲存方案探討

IM開發基礎知識補課(二):如何設計大量圖片檔案的服務端儲存架構?

IM開發基礎知識補課(三):快速理解服務端資料庫讀寫分離原理及實踐建議

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

>> 更多同類文章 ……

[3] IM開發綜合文章:

從客戶端的角度來談談移動端IM的訊息可靠性和送達機制

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

騰訊技術分享:社交網路圖片的頻寬壓縮技術演進之路

IM開發基礎知識補課:正確理解前置HTTP SSO單點登陸介面的原理

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

移動端IM開發需要面對的技術問題

開發IM是自己設計協議用位元組流好還是字元流好?

請問有人知道語音留言聊天的主流實現方式嗎?

IM訊息送達保證機制實現(一):保證線上實時訊息的可靠投遞

IM訊息送達保證機制實現(二):保證離線訊息的可靠投遞

如何保證IM實時訊息的“時序性”與“一致性”?

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

IM單聊和群聊中的線上狀態同步應該用“推”還是“拉”?

IM群聊訊息如此複雜,如何保證不丟不重?

談談移動端 IM 開發中登入請求的優化

移動端IM登入時拉取資料如何作到省流量?

淺談移動端IM的多點登陸和訊息漫遊原理

完全自已開發的IM該如何設計“失敗重試”機制?

通俗易懂:基於叢集的移動端IM接入層負載均衡方案分享

微信對網路影響的技術試驗及分析(論文全文)

即時通訊系統的原理、技術和應用(技術論文)

開源IM工程“蘑菇街TeamTalk”的現狀:一場有始無終的開源秀

QQ音樂團隊分享:Android中的圖片壓縮技術詳解(上篇)

QQ音樂團隊分享:Android中的圖片壓縮技術詳解(下篇)

騰訊原創分享(一):如何大幅提升行動網路下手機QQ的圖片傳輸速度和成功率

騰訊原創分享(二):如何大幅壓縮行動網路下APP的流量消耗(上篇)

騰訊原創分享(二):如何大幅壓縮行動網路下APP的流量消耗(下篇)

如約而至:微信自用的移動端IM網路層跨平臺元件庫Mars已正式開源

基於社交網路的Yelp是如何實現海量使用者圖片的無失真壓縮的?

>> 更多同類文章 ……

(本文同步釋出於:http://www.52im.net/thread-1525-1-1.html


相關文章