node.js極速入門課程:進入學習
目前絕大多數的系統都少不了登入驗證的功能,這主要是為了儲存使用者的狀態,以此來限制使用者的各種行為,從而方便有效的控制使用者的許可權。比如一個使用者登陸微博,釋出、關注、評論的操作都應是在登入後的使用者狀態下進行的。
實現登入驗證的功能主要有Cookie&Session
、JWT
兩種方式,這一節我們將先對 Cookie&Session
的工作原理 做詳細的介紹,在之後的文章中會陸續對JWT
,以及如何使用Cookie&Session
和JWT
來完善前幾節我們搭建的簡易使用者管理系統進行講解。【相關教學推薦:】
我們知道,HTTP 是無狀態的。也就是說,HTTP 請求方和響應方間無法維護狀態,都是一次性的,它不知道前後的請求都發生了什麼。但有的場景下,我們需要維護狀態。最典型的,一個使用者登陸微博,釋出、關注、評論,都應是在登入後的使用者狀態下的。
這個時候就可以引入Cookie
與Session
來儲存使用者的登入狀態。
本篇文章主要介紹使用
Cookie-Session
來做登入驗證的工作原理,關於Cookie
與Session
的詳細介紹可查閱這位大佬的文章:
Cookie
是存放在瀏覽器中的,可以在瀏覽器中開啟控制檯
,選擇應用
,找到儲存
中的Cookie
進行檢視:
當用戶端向伺服器端傳送網路請求時瀏覽器會自動將Cookie
新增到請求頭中,這樣伺服器端就能獲取這個Cookie
,如下:
知道了這個原理後,我們就可以想到,如果在使用者登入系統時:使用者端由使用者的部分登入資訊(比如username
、id
等)生成一個Cookie
存放到瀏覽器中,那麼在這之後的每一次網路請求都會自動攜帶上該Cookie
。
之後讓伺服器端根據請求中是否攜帶Cookie
並且攜帶的Cookie
中是否存在有效的username
、id
來判斷使用者是否已經登入過了,這樣一來使用者的登入狀態不就被儲存下來了嗎。
回到上面我們提到的微博的例子,按照這種過程來說,當使用者登入過後Cookie
已經被儲存,這時當使用者進行釋出、關注、評論等需要登入才能使用的操作時我們就能提前判斷是否存在Cookie
,如果存在並且Cookie
中含有該使用者的id
,那麼我們就可以允許該使用者的這些操作(這些操作一般都是需要使用者的id
的,這時就可以從Cookie
中進行獲取)。相反的,如果Cookie
不存在或者Cookie
無效,那麼就禁止該使用者的這些操作。
說到這,你可能會問:既然一個Cookie
就能實現我們想要的效果,那為何還要使用Session
呢?
這是因為 Cookie
很容易被偽造! ,如果我們知道了Cookie
中存放的資訊是username
和id
(就算不知道,也可以在登入後的網路請求的請求體中找到Cookie
),那麼我們完全可以在不登入的情況下手動向瀏覽器儲存一個偽造的Cookie
:
說到這,你應該就能明白為什麼不能單獨使用Cookie
了吧。
Session
其實是基於Cookie
實現的,並且Session
儲存在伺服器端的記憶體或者資料庫中。
當使用者登入成功時,使用Cookie&Session
的登入驗證會進行以下操作:
由伺服器端生成Session
與SessionId
;
Session
一般是根據使用者登入的資訊,如使用者名稱、id
等進行生成。
如果把Session
比作是一把鎖,那麼SessionId
就相當於是這把鎖的鑰匙。
伺服器端將Session
儲存到記憶體或者資料庫中;
伺服器端將SessionId
存放到請求的響應頭(response
物件)中的Set-Cookie
欄位中傳送給使用者端;
使用者端收到Set-Cookie
後會自動將Set-Cookie
的值(也就是SessionId
)存放到Cookie
中;
之後的每次網路請求都會自動帶上Cookie
,也就是帶上這個SessionId
;
伺服器端收到後續請求時獲取請求上的Cookie
,也就是獲取到了SessionId
,然後通過SessionId
查詢並校驗伺服器端儲存的Session
,若校驗成功說明這個SessionId
有效則通過此次請求,反之則阻止此次請求。
圖示:
為了儲存使用者的登入狀態,我們需要為每一位登入的使用者生成並儲存Session
,這勢必就會造成以下問題:
Session
存放到記憶體中,那麼當伺服器端重新啟動時,這些記憶體中的Session
都將被清除,那麼所有使用者的登入狀態都將會過期,並且當使用者量較大時,過多的記憶體佔用也勢必會影響伺服器端的效能。Session
存放到資料庫中,雖然能夠解決因伺服器端重新啟動造成使用者登入狀態過期的問題,但當使用者量較大時,對於這個資料庫的維護也會變得相對困難。Session
在兩個伺服器間共用通常會將Session
存放到一個單獨的資料庫中,這樣就使得整個專案變得更為複雜也更加難以維護。全稱為 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
不久,登入資訊尚未過期(網站A
的Cookie
存在且有效)。
那麼當 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其它相關文章!