開闊思維,HTTP Session 的工作原理以及幾個思維擴展

 2023-10-08 阅读 19 评论 0

摘要:大家都知道,HTTP 協議本身是無狀態的,Session 的出現解決了這個問題,也被大多數 Web 端采用。 但它背后的實現原理你是否有興趣了解呢,以及在它基礎上的思維發散,和你聊聊。 無狀態的 HTTP 大家都知道,我們目前使用的互聯網應用層

大家都知道,HTTP 協議本身是無狀態的,Session 的出現解決了這個問題,也被大多數 Web 端采用。 但它背后的實現原理你是否有興趣了解呢,以及在它基礎上的思維發散,和你聊聊。

無狀態的 HTTP

大家都知道,我們目前使用的互聯網應用層協議基本上都是基于 HTTP 和 HTTPS 的,它們的本身是無狀態的, 只負責請求和響應。 我告訴服務器我需要什么,服務器返回給我相應的資源。開闊思維, 如果沒有額外處理的話, 服務器是不知道你是誰,更無法根據你是誰給你展現和你相關的內容了。

HTTP 協議一開始被設計成這樣還是有一些歷史原因的,當時的互聯網多用于學術交流,只用于文章信息的展現之類的事情,遠沒有現在這么豐富多彩。所以在當時的背景下 HTTP 協議被設計成這樣其實也是很符合它的場景的。

但隨著互聯網應用越來越廣泛,應用的形式也變得越來越多,我們的 Web 應用不只限于提供簡單的信息展現了,還需要用戶能夠登錄,可以在論壇發帖子,在購物網站買東西等等。什么是思維、 這就需要 HTTP 協議能夠記錄用戶的狀態。也就是我們現在熟悉的 Session 由來。

Session 如何實現

大多數 Web 框架都提供了操作 Session 的 API。 如果你有 Web 端開發的經驗,那么你對這樣的代碼應該不會陌生:

 
  1. session["name"]?=?"xxx";?

我們給 session 對象設置一個值,比如用戶登錄成功后,給他設置一個用戶名,這樣我們這個用戶的狀態就保存下來了。拓展思維, 并且后續的請求中,這個狀態都可以讀取到。這一切就這么自動的發生了,并且習以為常。那么這一行代碼背后發生了什么呢? 就是下面幾個步驟。

生成 Session ID

關于 Session 的工作原理, 其實還是值得我們了解一下的。開拓思維、 我們調用上面這行代碼后,我們使用的 Web 框架首先會給當前請求創建一個 Session ID。 這個 Session ID 是通過一系列算法生成的一個唯一字符串。 這也是一個 Web 框架(PHP, Ruby on Rails, ExpressJS 等)提供的基礎能力,每個框架生成 Sesssion ID 的具體實現算法可能有所差別,但整體流程都是一樣的。

建立服務端 Session 存儲結構

這個新生成的 Session ID 用于標識這次發起請求的用戶,并存儲到服務器的某個區域中(默認情況下會在內存中)。工作原理, 這個 Session ID 同樣也是本地存儲的一個 key,比如我們上面代碼中設置了 name 屬性,就相當于在這個 key 中設置了對應的屬性。 這樣說起來可能有點抽象,舉個例子 Session 在服務端的存儲結構大概相當于這樣:

 
  1. {??
  2. "session-id-1":?{??
  3. "name"?:?"xxx"??
  4. },??
  5. "session-id-2":?{??
  6. "name"?:?"xxx"??
  7. }??
  8. //...??
  9. }??
  10. }?

服務端會保存這樣一個字典, 將每個用戶的 Session ID 和對應的屬性都記錄下來。

把 Session ID 返回給用戶瀏覽器

還繼續我們剛才的流程,生成完 Session ID 并建立好本地存儲結構后, 服務端會在返回給用戶的 HTTP 響應消息中帶上這個 Session ID:

HTTP Session 的工作原理以及幾個思維擴展

如上圖, 通過 Response Header 的 set-cookie 帶上,這樣截圖使用的是基于 Express 的 NodeJS 服務端框架, 這里面的 connect.sid=xxx 就是服務端給這個用戶生成的 Session ID。

這樣,用戶的瀏覽器得到這個 Cookie 后,再下一次請求同一個網站的時候就會在請求中帶上這個 Cookie。思維,

如果你對 Cookie 的細節不熟悉的話,不用多想,你可以理解成這樣 — 你用的所有瀏覽器都會有這個邏輯,收到 set-cookie 響應頭后,就會把里面的內容保存下來,下一次再訪問同樣的站點時候,就會把之前保存的 cookie 再重新發送回去。當然,關于 Cookie 的細節還有很多知識,不過理解我的這個簡單解釋就足夠了,感興趣的話可以再深入研究。

客戶端發送 Session ID

就會像我們剛說的,瀏覽器下一次再請求這個網站時,會把之前保存的 Session ID 再重新發給服務端。 這時候服務端就會用這個 Session ID 和它之前建立的存儲結構中進行匹配,如果這個 Session ID 是之前合法創建的,那么就可以從服務端存儲中得到用戶之前的狀態了,比如登錄用戶名之類的。簡述http協議的工作原理。 比如:

 
  1. {??
  2. //...??
  3. "session-id-1":?{??
  4. "name"?:?"xxx"??
  5. }??
  6. //...??
  7. }?

假設上面是我們服務端建立的本地 Session 數據存儲,如果 Session ID 正確匹配,就能找到對應這個用戶的 name 屬性了。

整體步驟

上面給大家介紹的就是 Session 整體的工作過程。 大概分為這幾個步驟:

  • 瀏覽器第一次請求網站, 服務端生成 Session ID。
  • 把生成的 Session ID 保存到服務端存儲中。
  • 把生成的 Session ID 返回給瀏覽器,通過 set-cookie。
  • 瀏覽器收到 Session ID, 在下一次發送請求時就會帶上這個 Session ID。
  • 服務端收到瀏覽器發來的 Session ID,從 Session 存儲中找到用戶狀態數據,會話建立。
  • 此后的請求都會交換這個 Session ID,進行有狀態的會話。

擴展知識

看完這一套流程后,是不是對我們開始的那一行代碼背后發生的事情了解的更通透了呢。還有幾個值得討論的地方也和大家聊聊。

1. Session ID

首先就是 Session ID,如果你理解了前面的介紹后,就會得到一個知識,在整個會話過程中,最重要的就是 Session ID。一個相對成熟的 Web 應用,往往會同時處理成百上千,甚至更大量的用戶同時在線。 這就對 Session ID 的創建有一個非常重要的要求,那就是在保證生成性能的同時,不能重復!

可以想象,如果你的 Web 框架在生成 Session ID 的時候重復了,會發生什么事情 — 用戶會誤登錄進別人的賬號, 這個后果還是非常嚴重的。 好在現在成熟的 Web 框架都考慮到了這個問題,你知識框架的使用者,所以你不必過于擔心。但了解背后的這個原理以及思維方式還是有助于你寫出更安全的程序的。

2. Session 數據存儲

另外一個要聊聊的就是 Session 數據的存儲。 通常情況下,如果你不明確的設置, 大多數 Web 框架會把 Session 數據存放到內存中。如果你的 Web 應用用戶量不大的話,這也不成問題。 但如果你的用戶數比較大的話,就可能發生一個事情 — 內存不夠用了。

這很正常,內存容量是非常寶貴的,假設每個用戶的 Session 數據是 100K, 1萬個用戶就會大概占用 1G 的存儲空間,如果你的 Session 數據清理機制也恰巧比較慢的話,內存非常容易被占滿。

這就需要你在設計比較大并發量的站點時,要考慮 Session 的存儲方式,比如把它們保存到硬盤文件系統中,或者數據庫中。 所以你在開發一個 Web 應用的時候,如果你的用戶量很大,你需要有這個意識。

另外 Session 放到內存中還有一個弊端,如果你的 Web 服務器發生重啟,那么所有的 Session 狀態都會被情況,會在一定程度上影響用戶體驗。

3. 傳輸安全

最后再聊聊傳輸安全,有一種叫做 Session ID 劫持的,假如 Session ID 是基于 HTTP 協議傳輸的,因為是明文傳輸,那么它就可能被中間的路由器劫持。 攻擊者得到 Session ID 后,把它帶到自己的請求中,就能夠進入你的賬戶。

所以一些 Web 框架還提供了 Session 的一些安全保護,比如間隔時間內動態刷新 Session ID,加上 Token 等。但這些也無法完全保證不被中間人看到。 其實從這個角度也間接體現了為什么 HTTPS 這么重要。

總結

這次跟大家聊了一下 HTTP Session 的原理和整個工作過程。 透過對它的了解,不僅是對細節的掌握,更重要的是這些知識能夠幫助我們理清對技術整體的思維方式。 包括我們最后說的 Session ID 生成機制。為什么把 Session 放到內存中會有問題,這樣才會理解框架為什么要提供硬盤和數據庫之類的其他 Session 存儲方式。無論你使用什么框架,什么語言,這些原理性的東西都是不變的。了解的多了,你也就越來越不用焦慮學哪種技術有前途這個問題了。




本文作者:佚名
來源:51CTO

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/131171.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息