1. 程式人生 > >小白必讀:閑話HTTP短連接中的Session和Token

小白必讀:閑話HTTP短連接中的Session和Token

caption 之路 1年 機制 視頻 挑戰 tps 每一個 負載

本文引用了劉欣的文章,感謝原作者的分享。

1、引言

Http協議在現今主流的IM系統中擁有無可替代的重要性(在IM系統中用HTTP發起的連接被大家簡稱為http短連接),但Http作為傳統互聯網信息交換技術,一些典型的概念比如:Session、Token,對於新手程序員來說很陌生。

很多文章動輒長篇大論、高屋建瓴地從底層協議再到上層分布式應用式的講解,根本不適合傻白甜程序員,本文的寫作目的是以最白話地方式,通俗易懂的為你講清HTTP協議中的Session和Token等概念,希望讀完全文,您仍能滿懷信心,繼續義無反顧地跳入程序員這個職業深坑 ^_^。更深入的技術細節,請閱讀《IM開發基礎知識補課(四):正確理解HTTP短連接中的Cookie、Session和Token》。

學習交流:

- 即時通訊開發交流3群:185926912[推薦]

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

(本文同步發布於:http://www.52im.net/thread-1686-1-1.html)

2、互聯網源起

1990年12月25日,羅伯特·卡裏奧在CERN(即位於日內瓦的歐洲原子核研究會)和蒂姆·伯納斯·李一起成功通過Internet實現了HTTP代理與服務器的第一次通訊(有關HTTP的詳細介紹,請見《網絡編程懶人入門(六):深入淺出,全面理解HTTP協議》)。蒂姆·伯納斯·李(Tim Berners-Lee)爵士作為萬維網(World Wide Web,簡稱WWW或互聯網)的發明者,被尊稱為互聯網之父。蒂姆·伯納斯·李建立的第一個網站(也是世界上第一個網站)是http://info. cern. ch/,它於1991年8月6日上網(即北京時間8月7日)。

技術分享圖片 ▲ 互聯網之父——伯納斯·李(Tim Berners-Lee)

1955年6月8日,伯納斯·李出生於英格蘭倫敦西南部。他的父母都參與了世界上第一臺商業電腦,曼切斯特1型(Manchester Mark I)的建造。2017年,他因“發明萬維網、第一個瀏覽器和使萬維網得以擴展的基本協議和算法”而獲得2016年度的圖靈獎,同時還有100萬美元獎金(該獎金由谷歌公司提供)。

技術分享圖片 ▲ 圖靈獎獎杯實物

在此前的倫敦2012奧運會開幕式上,開幕式總導演丹尼·博伊爾特別為表揚蒂姆·伯納斯·李爵士的功績,設計了激動人心的一幕:蒂姆·伯納斯·李爵士在“倫敦碗”場館中央用電腦鍵盤敲出了一句話:This Is For Everyone(為了每一個人)。

媒體評述:“如果蒂姆·伯納斯-李爵士為互聯網申請專利,他將是世界最富有的萬億富豪”。但是,蒂姆·伯納斯-李爵士將他的發明無償貢獻給全人類。

技術分享圖片 ▲ 蒂姆·伯納斯·李爵士參與了倫敦奧運2012開幕式的表演 技術分享圖片 ▲ 蒂姆·伯納斯·李爵士在“倫敦碗”場館中央用鍵盤敲下的“This is For Everyone” 技術分享圖片 ▲ 現在的“互聯網”已無比龐大

(本圖來自:《技術往事:改變世界的TCP/IP協議(珍貴多圖、手機慎點)》一文)

3、相關文章

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

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

《移動端IM登錄時拉取數據如何作到省流量?》

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

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

《談談移動端 IM 開發中登錄請求的優化》

好了,我們開始正文的閱讀。

4、美好的舊時光

我經常想象並懷念三十年前那原始而美好的互聯網舊時光, 工作很輕松, 生活很悠閑。

上班的時候偶爾有些HTTP的請求發到我這裏, 我簡單的看一下, 取出相對應的html文檔,圖片,發回去就可以了, 然後就可以繼續喝茶聊天。

技術分享圖片 ▲ 早期IE瀏覽器界面

我的創造者們對我很好, 他們制定的一個簡單HTTP協議, 就是請求加響應, 尤其是我不用記住是誰剛剛發了HTTP請求, 每個請求對我來說都是全新的!

郵件服務器很羨慕我, 他說:老弟,你的生活太愜意了, 哪像我, 每次有人從客戶端訪問郵箱, 我都得專門給他建立一個會話, 來處理他發的消息, 你倒好, 完全不用管理會話。

這是由應用的特性決定的, 如果郵件服務器不管理會話, 那多個人之間的郵件消息就會完全混到一起了, 亂作一團了。

而30年前的Web 基本上就是文檔的瀏覽而已, 既然是瀏覽,我作為一個服務器, 為什麽要記住誰在一段時間裏都瀏覽了什麽文檔呢?

5、是時候該Session出場了

但是好日子沒持續多久, 很快大家就不滿足於靜態的Html 文檔了, 交互式的Web應用開始興起, 尤其是論壇, 在線購物等網站。

我馬上就遇到了和郵件服務器一樣的問題, 那就是必須管理會話,必須記住哪些人登錄系統, 哪些人往自己的購物車中放了商品, 也就是說我必須把每個人區分開。

這對我來說是個不小的挑戰, 由於HTTP協議的無狀態特性, 我必須加點小手段,才能完成會話管理。

我想出的辦法就是給大家發一個會話標識(session id), 說白了就是一個隨機的字符串,每個人收到的都不一樣, 每次大家向我發起HTTP請求的時候,把這個字符串給一並捎過來, 這樣我就能區分開誰是誰了。

6、沈重的負擔

大家都很高興, 可是我就不爽了。

每個人只需要保存自己的session id,而我需要保存所有人的session id ! 如果訪問我的人多了, 就得由成千上萬,甚至幾十萬個。

這對我來說是一個巨大的開銷 , 嚴重的限制了我的擴展能力, 比如說我用兩個機器組成了一個集群, 小F通過機器A登錄了系統, 那session id會保存在機器A上, 假設小F的下一次請求被轉發到機器B怎麽辦? 機器B可沒有小F的 session id啊。

有時候我會采用一點小伎倆: session sticky , 就是讓小F的請求一直粘連在機器A上, 但是這也不管用, 要是機器A掛掉了, 還得轉到機器B去。

那我只好做session 的復制了, 把session id 在兩個機器之間搬來搬去, 快累死了。

技術分享圖片

後來有個叫Memcached的給我支了招: 把session id 集中存儲到一個地方, 所有的機器都來訪問這個地方的數據, 這樣一來,就不用復制了, 但是增加了單點失敗的可能性, 要是那個負責session 的機器掛了, 所有人都得重新登錄一遍, 估計得被人罵死。

技術分享圖片

我也嘗試把這個單點的機器也搞出集群,增加可靠性, 但不管如何, 這小小的session 對我來說是一個沈重的負擔。

7、時間換空間:Token是個不錯的方案

這幾天的晚上我一直在思考, 我為什麽要保存這可惡的session呢, 只讓每個客戶端去保存該多好?

可是如果我不保存這些session id , 我怎麽驗證客戶端發給我的session id 的確是我生成的呢? 如果我不去驗證,我都不知道他們是不是合法登錄的用戶, 那些不懷好意的家夥們就可以偽造session id , 為所欲為了。

嗯,對了,關鍵點就是驗證 !

比如說, 小F已經登錄了系統, 我給他發一個令牌(token), 裏邊包含了小F的 user id, 下一次小F 再次通過Http 請求訪問我的時候, 把這個token 通過Http header 帶過來不就可以了。

不過這和session id沒有本質區別啊, 任何人都可以可以偽造, 所以我得想點兒辦法, 讓別人偽造不了。

那就對數據做一個簽名吧, 比如說我用HMAC-SHA256 算法,加上一個只有我才知道的密鑰, 對數據做一個簽名, 把這個簽名和數據一起作為token , 由於密鑰別人不知道, 就無法偽造token了。

技術分享圖片

這個token 我不保存, 當小F把這個token 給我發過來的時候,我再用同樣的HMAC-SHA256 算法和同樣的密鑰,對數據再計算一次簽名, 和token 中的簽名做個比較, 如果相同, 我就知道小F已經登錄過了,並且可以直接取到小F的user id , 如果不相同, 數據部分肯定被人篡改過, 我就告訴發送者: 對不起,沒有認證。

技術分享圖片

Token 中的數據是明文保存的(雖然我會用Base64做下編碼, 但那不是加密), 還是可以被別人看到的, 所以我不能在其中保存像密碼這樣的敏感信息。

當然, 如果一個人的token 被別人偷走了, 那我也沒辦法, 我也會認為小偷就是合法用戶, 這其實和一個人的session id 被別人偷走是一樣的。

這樣一來, 我就不保存session id 了, 我只是生成token , 然後驗證token , 我用我的CPU計算時間獲取了我的session 存儲空間 !

解除了session id這個負擔, 可以說是無事一身輕, 我的機器集群現在可以輕松地做水平擴展, 用戶訪問量增大, 直接加機器就行。這種無狀態的感覺實在是太好了!

附錄:IM開發綜合性文章

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

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

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

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

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

《小白必讀:閑話HTTP短連接中的Session和Token》

《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是如何實現海量用戶圖片的無損壓縮的?》

《騰訊技術分享:騰訊是如何大幅降低帶寬和網絡流量的(圖片壓縮篇)》

《騰訊技術分享:騰訊是如何大幅降低帶寬和網絡流量的(音視頻技術篇)》

《為什麽說即時通訊社交APP創業就是一個坑?》

>> 更多同類文章 ……

(本文同步發布於:http://www.52im.net/thread-1686-1-1.html)

小白必讀:閑話HTTP短連接中的Session和Token