Node學習之聊聊Cookie-Session登入驗證的工作原理

2022-11-30 22:00:18

node.js極速入門課程:進入學習

目前絕大多數的系統都少不了登入驗證的功能,這主要是為了儲存使用者的狀態,以此來限制使用者的各種行為,從而方便有效的控制使用者的許可權。比如一個使用者登陸微博,釋出、關注、評論的操作都應是在登入後的使用者狀態下進行的。

實現登入驗證的功能主要有Cookie&SessionJWT兩種方式,這一節我們將先對 Cookie&Session的工作原理 做詳細的介紹,在之後的文章中會陸續對JWT,以及如何使用Cookie&SessionJWT來完善前幾節我們搭建的簡易使用者管理系統進行講解。【相關教學推薦:】

1️⃣ Cookie&Session

我們知道,HTTP 是無狀態的。也就是說,HTTP 請求方和響應方間無法維護狀態,都是一次性的,它不知道前後的請求都發生了什麼。但有的場景下,我們需要維護狀態。最典型的,一個使用者登陸微博,釋出、關注、評論,都應是在登入後的使用者狀態下的。

這個時候就可以引入CookieSession來儲存使用者的登入狀態。

本篇文章主要介紹使用Cookie-Session來做登入驗證的工作原理,關於CookieSession的詳細介紹可查閱這位大佬的文章:

為什麼不單獨使用Cookie?

Cookie是存放在瀏覽器中的,可以在瀏覽器中開啟控制檯,選擇應用,找到儲存中的Cookie進行檢視:

在這裡插入圖片描述

當用戶端向伺服器端傳送網路請求時瀏覽器會自動Cookie新增到請求頭中,這樣伺服器端就能獲取這個Cookie,如下:

在這裡插入圖片描述

知道了這個原理後,我們就可以想到,如果在使用者登入系統時:使用者端由使用者的部分登入資訊(比如usernameid等)生成一個Cookie存放到瀏覽器中,那麼在這之後的每一次網路請求都會自動攜帶上該Cookie

之後讓伺服器端根據請求中是否攜帶Cookie並且攜帶的Cookie中是否存在有效的usernameid來判斷使用者是否已經登入過了,這樣一來使用者的登入狀態不就被儲存下來了嗎。

回到上面我們提到的微博的例子,按照這種過程來說,當使用者登入過後Cookie已經被儲存,這時當使用者進行釋出、關注、評論等需要登入才能使用的操作時我們就能提前判斷是否存在Cookie,如果存在並且Cookie中含有該使用者的id,那麼我們就可以允許該使用者的這些操作(這些操作一般都是需要使用者的id的,這時就可以從Cookie中進行獲取)。相反的,如果Cookie不存在或者Cookie無效,那麼就禁止該使用者的這些操作。

說到這,你可能會問:既然一個Cookie就能實現我們想要的效果,那為何還要使用Session呢?

這是因為 Cookie很容易被偽造! ,如果我們知道了Cookie中存放的資訊是usernameid(就算不知道,也可以在登入後的網路請求的請求體中找到Cookie),那麼我們完全可以在不登入的情況下手動向瀏覽器儲存一個偽造的Cookie

在這裡插入圖片描述

說到這,你應該就能明白為什麼不能單獨使用Cookie了吧。

Session是如何與Cookie結合的?

Session其實是基於Cookie實現的,並且Session儲存在伺服器端的記憶體或者資料庫中。

當使用者登入成功時,使用Cookie&Session的登入驗證會進行以下操作:

  • 由伺服器端生成SessionSessionId

    Session一般是根據使用者登入的資訊,如使用者名稱、id等進行生成。
    如果把Session比作是一把鎖,那麼SessionId就相當於是這把鎖的鑰匙。

  • 伺服器端將Session儲存到記憶體或者資料庫中;

  • 伺服器端將SessionId存放到請求的響應頭(response物件)中的Set-Cookie欄位中傳送給使用者端;

  • 使用者端收到Set-Cookie後會自動將Set-Cookie的值(也就是SessionId)存放到Cookie中;

  • 之後的每次網路請求都會自動帶上Cookie,也就是帶上這個SessionId

  • 伺服器端收到後續請求時獲取請求上的Cookie,也就是獲取到了SessionId,然後通過SessionId查詢並校驗伺服器端儲存的Session,若校驗成功說明這個SessionId有效則通過此次請求,反之則阻止此次請求。

圖示:

在這裡插入圖片描述

2️⃣ Cookie&Session的缺陷

儲存問題

為了儲存使用者的登入狀態,我們需要為每一位登入的使用者生成並儲存Session,這勢必就會造成以下問題:

  • 如果Session存放到記憶體中,那麼當伺服器端重新啟動時,這些記憶體中的Session都將被清除,那麼所有使用者的登入狀態都將會過期,並且當使用者量較大時,過多的記憶體佔用也勢必會影響伺服器端的效能。
  • 如果Session存放到資料庫中,雖然能夠解決因伺服器端重新啟動造成使用者登入狀態過期的問題,但當使用者量較大時,對於這個資料庫的維護也會變得相對困難。
  • 如果前端頁面中呼叫的介面來自兩個伺服器(也就是兩套資料庫),為了實現Session在兩個伺服器間共用通常會將Session存放到一個單獨的資料庫中,這樣就使得整個專案變得更為複雜也更加難以維護。
    在這裡插入圖片描述

CSRF問題

全稱為 Cross-site request forgery 即 跨站請求偽造,使用Cookie進行驗證的網站都會面臨或大或小的CSRF威脅,我們以一個銀行網站的例子來介紹CSRF的攻擊原理:

假如一家銀行網站A的登入驗證採用的是Cookie&Session,並且該網站上用以執行轉賬操作Api地址為:http://www.grillbankapi.com/?account=AccoutName&amount=1000

api引數:account代表賬戶名,amount代表轉賬金額。

那麼,一個惡意攻擊者可以在另一個網站B上放置如下程式碼:

<img src="http://www.grillbankapi.com/?account=Ailjx&amount=1000">
登入後複製

注意:img標籤的src網站A轉賬操作的api地址,並且引數account為Ailjx,amount為1000,也就是說這個api地址相當於是賬戶名為 Ailjx 轉賬1000 時呼叫的api

如果有賬戶名為 Ailjx 的使用者剛存取過網站A不久,登入資訊尚未過期(網站ACookie存在且有效)。

那麼當 Ailjx 存取了這個惡意網站B時,上面的img標籤將被載入,瀏覽器就會自動請求img標籤的src路由,也就是請求http://www.grillbankapi.com/?account=Ailjx&amount=1000 (我們將這個請求記為請求Q),並且因為Cookie存放在瀏覽器中且瀏覽器傳送請求時會自動帶上Cookie,所以請求Q上就會自動攜帶 Ailjx 在網站A上的Cookie憑證,結果就是這個 請求Q將會被通過,那麼 Ailjx 就會損失1000資金

這種惡意的網址可以有很多種形式,藏身於網頁中的許多地方。 此外,攻擊者也不需要控制放置惡意網址的網站。例如他可以將這種地址藏在論壇,部落格等任何使用者生成內容的網站中。這意味著如果伺服器端沒有合適的防禦措施的話,使用者即使存取熟悉的可信網站也有受攻擊的危險。

透過例子能夠看出,攻擊者並不能通過CSRF攻擊來直接獲取使用者的賬戶控制權,也不能直接竊取使用者的任何資訊。他們能做到的,是欺騙使用者瀏覽器,讓其以使用者的名義執行操作。

這些就是使用Cookie&Session來做登入驗證的問題所在,那麼我們如何解決這些問題呢?這就需要引入JWT的概念,使用token來做登入驗證,這些我們將在之後的文章中進行講解。

更多node相關知識,請存取:!

以上就是Node學習之聊聊Cookie-Session登入驗證的工作原理的詳細內容,更多請關注TW511.COM其它相關文章!