本篇內(nèi)容主要講解“Cookie/Session/Token的區(qū)別有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Cookie/Session/Token的區(qū)別有哪些”吧!
10年積累的成都網(wǎng)站制作、做網(wǎng)站、外貿(mào)營銷網(wǎng)站建設經(jīng)驗,可以快速應對客戶對網(wǎng)站的新想法和需求。提供各種問題對應的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡服務。我雖然不認識你,你也不認識我。但先網(wǎng)站制作后付款的網(wǎng)站建設流程,更有清澗免費網(wǎng)站建設讓你可以放心的選擇與我們合作。
Cookie
眾所周知,http 是無狀態(tài)協(xié)議,瀏覽器和服務器不可能憑協(xié)議的實現(xiàn)辨別請求的上下文。
于是 cookie 登場,既然協(xié)議本身不能分辨鏈接,那就在請求頭部手動帶著上下文信息吧。
舉個例子,以前去旅游的時候,到了景區(qū)可能會需要存放行李,被大包小包壓著,旅游也不開心啦。在存放行李后,服務員會給你一個牌子,上面寫著你的行李放在哪個格子,離開時,你就能憑這個牌子和上面的數(shù)字成功取回行李。
cookie 做的正是這么一件事,旅客就像客戶端,寄存處就像服務器,憑著寫著數(shù)字的牌子,寄存處(服務器)就能分辨出不同旅客(客戶端)。
你會不會想到,如果牌子被偷了怎么辦,cookie 也會被偷嗎?確實會,這就是一個很常被提到的網(wǎng)絡安全問題——CSRF??梢栽谶@篇文章了解關于 CSRF 的成因和應對方法。
cookie 誕生初似乎是用于電商存放用戶購物車一類的數(shù)據(jù),但現(xiàn)在前端擁有兩個 storage(local、session),兩種數(shù)據(jù)庫(websql、IndexedDB),根本不愁信息存放問題,所以現(xiàn)在基本上 100% 都是在連接上證明客戶端的身份。例如登錄之后,服務器給你一個標志,就存在 cookie 里,之后再連接時,都會自動帶上 cookie,服務器便分清誰是誰。另外,cookie 還可以用于跟蹤一個用戶,這就產(chǎn)生了隱私問題,于是也就有了“禁用 cookie”這個選項(然而現(xiàn)在這個時代禁用 cookie 是挺麻煩的事情)。
設置方式
現(xiàn)實世界的例子明白了,在計算機中怎么才能設置 cookie 呢?一般來說,安全起見,cookie 都是依靠 set-cookie 頭設置,且不允許 JavaScript 設置。
Set-Cookie:= Set-Cookie: = ; Expires= Set-Cookie: = ; Max-Age= Set-Cookie: = ; Domain= Set-Cookie: = ; Path= Set-Cookie: = ; Secure Set-Cookie: = ; HttpOnly Set-Cookie: = ; SameSite=Strict Set-Cookie: = ; SameSite=Lax Set-Cookie: = ; SameSite=None; Secure // Multiple attributes are also possible, for example: Set-Cookie: = ; Domain= ; Secure; HttpOnly
其中
Expires 設置 cookie 的過期時間(時間戳),這個時間是客戶端時間。
Max-Age 設置 cookie 的保留時長(秒數(shù)),同時存在 Expires 和 Max-Age 的話,Max-Age 優(yōu)先
Domain 設置生效的域名,默認就是當前域名,不包含子域名
Path 設置生效路徑,/ 全匹配
Secure 設置 cookie 只在 https 下發(fā)送,防止中間人攻擊
HttpOnly 設置禁止 JavaScript 訪問 cookie,防止XSS
SameSite 設置跨域時不攜帶 cookie,防止CSRF
Secure 和 HttpOnly 是強烈建議開啟的。SameSite 選項需要根據(jù)實際情況討論,因為 SameSite 可能會導致即使你用 CORS 解決了跨越問題,依然會因為請求沒自帶 cookie 引起一系列問題,一開始還以為是 axios 配置問題,繞了一大圈,然而根本沒關系。
其實因為 Chrome 在某一次更新后把沒設置 SameSite 默認為 Lax,你不在服務器手動把 SameSite 設置為 None 就不會自動帶 cookie 了。
發(fā)送方式
參考 MDN,cookie 的發(fā)送格式如下(其中 PHPSESSID 相關內(nèi)容下面會提到):
Cookie:Cookie: name=value Cookie: name=value; name2=value2; name3=value3 Cookie: PHPSESSID=298zf09hf012fh3; csrftoken=u32t4o3tb3gg43; _gat=1
在發(fā)送 cookie 時,并不會傳上面提到的配置到服務器,因為服務器在設置后就不需要關心這些信息了,只要現(xiàn)代瀏覽器運作正常,收到的 cookie 就是沒問題的。
Session
從 cookie 說到 session,是因為 session 才是真正的“信息”,如上面提到的,cookie 是容器,里面裝著 PHPSESSID=298zf09hf012fh3;,這就是一個 session ID。
不知道 session 和 session id 會不會讓你看得有點頭暈?
當初 session 的存在就是要為客戶端和服務器連接提供的信息,所以我將 session 理解為信息,而 session id 是獲取信息的鑰匙,通常是一串唯一的哈希碼。
接下來分析兩個 node.js express 的中間件,理解兩種 session 的實現(xiàn)方式。
session 信息可以儲存在客戶端,如 cookie-session,也可以儲存在服務器,如 express-session。使用 session ID 就是把 session 放在服務器里,用 cookie 里的 id 尋找服務器的信息。
客戶端儲存
對于 cookie-session 庫,比較容易理解,其實就是把所有信息加密后塞到 cookie 里。其中涉及到 cookies 庫。在設置 session 時其實就是調(diào)用 cookies.set,把信息寫到 set-cookie 里,再返回瀏覽器。換言之,取值和賦值的本質(zhì)都是操作 cookie。
瀏覽器在接收到 set-cookie 頭后,會把信息寫到 cookie 里。在下次發(fā)送請求時,信息又通過 cookie 原樣帶回來,所以服務器什么東西都不用存,只負責獲取和處理 cookie 里的信息,這種實現(xiàn)方法不需要 session ID。
這是一段使用 cookie-session 中間件為請求添加 cookie 的代碼:
const express = require('express') var cookieSession = require('cookie-session') const app = express() app.use( cookieSession({ name: 'session', keys: [ /* secret keys */ 'key', ], // Cookie Options maxAge: 24 * 60 * 60 * 1000, // 24 hours }) ) app.get('/', function(req, res) { req.session.test = 'hey' res.json({ wow: 'crazy', }) }) app.listen(3001)
在通過 app.use(cookieSession()) 使用中間件之前,請求是不會設置 cookie 的,添加后再訪問(并且在設置 req.session 后,若不添加 session 信息就沒必要寫、也沒內(nèi)容寫到 cookie 里),就能看到服務器響應頭部新增了下面兩行,分別寫入 session 和 session.sig:
Set-Cookie: session=eyJ0ZXN0IjoiaGV5In0=; path=/; expires=Tue, 23 Feb 2021 01:07:05 GMT; httponly Set-Cookie: session.sig=QBoXofGvnXbVoA8dDmfD-GMMM6E; path=/; expires=Tue, 23 Feb 2021 01:07:05 GMT; httponly
然后你就能在 DevTools 的 Application 標簽看到 cookie 成功寫入。session 的值 eyJ0ZXN0IjoiaGV5In0= 通過 base64 解碼(不了解 base64 的話可以看這里)即可得到 {"test":"hey"},這就是所謂的“將 session 信息放到客戶端”,因為 base64 編碼并不是加密,這就跟明文傳輸沒啥區(qū)別,所以請不要在客戶端 session 里放用戶密碼之類的機密信息。
即使現(xiàn)代瀏覽器和服務器做了一些約定,例如使用 https、跨域限制、還有上面提到 cookie 的 httponly 和 sameSite 配置等,保障了 cookie 安全。但是想想,傳輸安全保障了,如果有人偷看你電腦里的 cookie,密碼又恰好存在 cookie,那就能無聲無息地偷走密碼。相反的,只放其他信息或是僅僅證明“已登錄”標志的話,只要退出一次,這個 cookie 就失效了,算是降低了潛在危險。
說回第二個值 session.sig,它是一個 27 字節(jié)的 SHA1 簽名,用以校驗 session 是否被篡改,是 cookie 安全的又一層保障。
服務器儲存
既然要儲存在服務器,那么 express-session 就需要一個容器 store,它可以是內(nèi)存、redis、MongoDB 等等等等,內(nèi)存應該是最快的,但是重啟程序就沒了,redis 可以作為備選,用數(shù)據(jù)庫存 session 的場景感覺不多。
express-session 的源碼沒 cookie-session 那么簡明易懂,里面有一個有點繞的問題,req.session 到底是怎么插入的?
不關注實現(xiàn)可以跳過這段,有興趣的話可以跟著思路看看 express-session 的源碼。
我們可以從 .session = 這個關鍵詞開始找,找到:
store.generate 否決這個,容易看出這個是初始化使用的
Store.prototype.createSession 這個是根據(jù) req 和 sess 參數(shù)在 req 中設置 session 屬性,沒錯,就是你了
于是全局搜索 createSession,鎖定 index 里的 inflate (就是填充的意思)函數(shù)。
最后尋找 inflate 的調(diào)用點,是使用 sessionID 為參數(shù)的 store.get 的回調(diào)函數(shù),一切說得通啦——
在監(jiān)測到客戶端送來的 cookie 之后,可以從 cookie 獲取 sessionID,再使用 id 在 store 中獲取 session 信息,掛到 req.session,經(jīng)過這個中間件,你就能順利地使用 req 中的 session。
那賦值怎么辦呢?這就和上面儲存在客戶端不同了,上面要修改客戶端 cookie 信息,但是對于儲存在服務器的情況,你修改了 session 那就是“實實在在地修改”了嘛,不用其他花里胡哨的方法,內(nèi)存中的信息就是修改了,下次獲取內(nèi)存里的對應信息也是修改后的信息。(僅限于內(nèi)存的實現(xiàn)方式,使用數(shù)據(jù)庫時仍需要額外的寫入)
在請求沒有 session id 的情況下,通過 store.generate 創(chuàng)建新的 session,在你寫 session 的時候,cookie 可以不改變,只要根據(jù)原來的 cookie 訪問內(nèi)存里的 session 信息就可以了。
var express = require('express') var parseurl = require('parseurl') var session = require('express-session') var app = express() app.use( session({ secret: 'keyboard cat', resave: false, saveUninitialized: true, }) ) app.use(function(req, res, next) { if (!req.session.views) { req.session.views = {} } // get the url pathname var pathname = parseurl(req).pathname // count the views req.session.views[pathname] = (req.session.views[pathname] || 0) + 1 next() }) app.get('/foo', function(req, res, next) { res.json({ session: req.session, }) }) app.get('/bar', function(req, res, next) { res.send('you viewed this page ' + req.session.views['/bar'] + ' times') }) app.listen(3001)
兩種儲存方式的對比
首先還是計算機世界最重要的哲學問題:時間和空間的抉擇。
儲存在客戶端的情況,解放了服務器存放 session 的內(nèi)存,但是每次都帶上一堆 base64 處理的 session 信息,如果量大的話傳輸就會很緩慢。
儲存在服務器相反,用服務器的內(nèi)存拯救了帶寬。
另外,在退出登錄的實現(xiàn)和結果,也是有區(qū)別的。
儲存在服務器的情況就很簡單,如果 req.session.isLogin = true 是登錄,那么 req.session.isLogin = false 就是退出。
但是狀態(tài)存放在客戶端要做到真正的“即時退出登錄”就很困難了。你可以在 session 信息里加上過期日期,也可以直接依靠 cookie 的過期日期,過期之后,就當是退出了。
但是如果你不想等到 session 過期,現(xiàn)在就想退出登錄!怎么辦?認真想想你會發(fā)現(xiàn),僅僅依靠客戶端儲存的 session 信息真的沒有辦法做到。
即使你通過 req.session = null 刪掉客戶端 cookie,那也只是刪掉了,但是如果有人曾經(jīng)把 cookie 復制出來了,那他手上的 cookie 直到 session 信息里的過期時間前,都是有效的。
說“即時退出登錄”有點標題黨的意味,其實我想表達的是,你沒辦法立即廢除一個 session,這可能會造成一些隱患。
Token
session 說完了,那么出現(xiàn)頻率超高的關鍵字 token 又是什么?
不妨谷歌搜一下 token 這個詞,可以看到冒出來幾個(年紀大的人)比較熟悉的圖片:密碼器。過去網(wǎng)上銀行不是只要短信認證就能轉(zhuǎn)賬,還要經(jīng)過一個密碼器,上面顯示著一個變動的密碼,在轉(zhuǎn)賬時你需要輸入密碼器中的代碼才能轉(zhuǎn)賬,這就是 token 現(xiàn)實世界中的例子。憑借一串碼或是一個數(shù)字證明自己身份,這事情不就和上面提到的行李問題還是一樣的嗎……
其實本質(zhì)上 token 的功能就是和 session id 一模一樣。你把 session id 說成 session token 也沒什么問題(Wikipedia 里就寫了這個別名)。
其中的區(qū)別在于,session id 一般存在 cookie 里,自動帶上;token 一般是要你主動放在請求中,例如設置請求頭的 Authorization 為 bearer:
然而上面說的都是一般情況,根本沒有明確規(guī)定!
劇透一下,下面要講的 JWT(JSON Web Token)!他是一個 token!但是里面放著 session 信息!放在客戶端,并且可以隨你選擇放在 cookie 或是手動添加在 Authorization!但是他就叫 token!
個人覺得你不能通過存放的位置判斷是 token 或是 session id,也不能通過內(nèi)容判斷是 token 或是 session 信息,session、session id 以及 token 都是很意識流的東西,只要你明白他是什么、怎么用就好了,怎么稱呼不太重要。
另外在搜索資料時也看到有些文章說 session 和 token 的區(qū)別就是新舊技術的區(qū)別,好像有點道理。
在 session 的 Wikipedia 頁面上 HTTP session token 這一欄,舉例都是 JSESSIONID (JSP)、PHPSESSID (PHP)、CGISESSID (CGI)、ASPSESSIONID (ASP) 等比較傳統(tǒng)的技術,就像 SESSIONID 是他們的代名詞一般;而在研究現(xiàn)在各種平臺的 API 接口和 OAuth3.0 登錄時,都是使用 access token 這樣的字眼,這個區(qū)別著實有點意思。
理解 session 和 token 的聯(lián)系之后,可以在哪里能看到“活的” token 呢?
打開 GitHub 進入設置,找到 Settings / Developer settings,可以看到 Personal access tokens 選項,生成新的 token 后,你就可以帶著它通過 GitHub API,證明“你就是你”。
在 OAuth 系統(tǒng)中也使用了 Access token 這個關鍵詞,寫過微信登錄的朋友應該都能感受到 token 是個什么啦。
Token 在權限證明上真的很重要,不可泄漏,誰拿到 token,誰就是“主人”。所以要做一個 Token 系統(tǒng),刷新或刪除 Token 是必須要的,這樣在盡快彌補 token 泄漏的問題。
在理解了三個關鍵字和兩種儲存方式之后,下面我們正式開始說“用戶登錄”相關的知識和兩種登錄規(guī)范——JWT 和 OAuth3.0。
接著你可能會頻繁見到 Authentication 和 Authorization 這兩個單詞,它們都是 Auth 開頭,但可不是一個意思,簡單來說前者是驗證,后者是授權。在編寫登錄系統(tǒng)時,要先驗證用戶身份,設置登錄狀態(tài),給用戶發(fā)送 token 就是授權。
JWT
全稱 JSON Web Token(RFC 7519),是的,JWT 就是一個 token。為了方便理解,提前告訴大家,JWT 用的是上面客戶端儲存的方式,所以這部分可能會經(jīng)常用到上面提到的名稱。
結構
雖說 JWT 就是客戶端儲存 session 信息的一種,但是 JWT 有著自己的結構:Header.Payload.Signature(分為三個部分,用 . 隔開)
Header
{ "alg": "HS256", "typ": "JWT" }
typ 說明 token 類型是 JWT,alg 代表簽名算法,HMAC、SHA256、RSA 等。然后將其 base64 編碼。
Payload
{ "sub": "1234567890", "name": "John Doe", "admin": true }
Payload 是放置 session 信息的位置,最后也要將這些信息進行 base64 編碼,結果就和上面客戶端儲存的 session 信息差不多。
不過 JWT 有一些約定好的屬性,被稱為 Registered claims,包括:
iss (issuer):簽發(fā)人
exp (expiration time):過期時間
sub (subject):主題
aud (audience):受眾
nbf (Not Before):生效時間
iat (Issued At):簽發(fā)時間
jti (JWT ID):編號
Signature
最后一部分是簽名,和上面提到的 session.sig 一樣是用于防止篡改,不過 JWT 把簽名和內(nèi)容組合到一起罷了。
JWT 簽名的生成算法是這樣的:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
使用 Header 里 alg 的算法和自己設定的密鑰 secret 編碼 base64UrlEncode(header) + "." + base64UrlEncode(payload)
最后將三部分通過 . 組合在一起,你可以通過 jwt.io Debugger 形象地看到 JWT 的組成原理:
如何使用
在驗證用戶,順利登錄后,會給用戶返回 JWT。因為 JWT 的信息沒有加密,所以別往里面放密碼,詳細原因在客戶端儲存的 cookie 中提到。
用戶訪問需要授權的連接時,可以把 token 放在 cookie,也可以在請求頭帶上 Authorization: Bearer
這樣可以用于自家登錄,也可以用于第三方登錄。單點登錄也是 JWT 的常用領域。
JWT 也因為信息儲存在客戶端造成無法讓自己失效的問題,這算是 JWT 的一個缺點。
HTTP authentication
HTTP authentication 是一種標準化的校驗方式,不會使用 cookie 和 session 相關技術。請求頭帶有 Authorization: Basic
其中 credentials 就是 Base64 編碼的用戶名 + : + 密碼(或 token),以后看到 Basic authentication,意識到就是每次請求都帶上用戶名密碼就好了。
Basic authentication 大概比較適合 serverless,畢竟他沒有運行著的內(nèi)存,無法記錄 session,直接每次都帶上驗證就完事了。
OAuth 2.0
OAuth 2.0(RFC 6749)也是用 token 授權的一種協(xié)議,它的特點是你可以在有限范圍內(nèi)使用別家接口,也可以借此使用別家的登錄系統(tǒng)登錄自家應用,也就是第三方應用登錄。(注意啦注意啦,OAuth 2.0 授權流程說不定面試會考哦!)
既然是第三方登錄,那除了應用本身,必定存在第三方登錄服務器。在 OAuth 2.0 中涉及三個角色:用戶、應用提供方、登錄平臺,相互調(diào)用關系如下:
+--------+ +---------------+ | |--(A)- Authorization Request ->| Resource | | | | Owner | | |<-(B)-- Authorization Grant ---| | | | +---------------+ | | | | +---------------+ | |--(C)-- Authorization Grant -->| Authorization | | Client | | Server | | |<-(D)----- Access Token -------| | | | +---------------+ | | | | +---------------+ | |--(E)----- Access Token ------>| Resource | | | | Server | | |<-(F)--- Protected Resource ---| | +--------+ +---------------+
很多大公司都提供 OAuth 2.0 第三方登錄,這里就拿小聾哥的微信舉例吧——
準備
一般來說,應用提供方需要先在登錄平臺申請好 AppID 和 AppSecret。(微信使用這個名稱,其他平臺也差不多,一個 ID 和一個 Secret)
獲取 code
什么是授權臨時票據(jù)(code)? 答:第三方通過 code 進行獲取 access_token 的時候需要用到,code 的超時時間為 10 分鐘,一個 code 只能成功換取一次 access_token 即失效。code 的臨時性和一次保障了微信授權登錄的安全性。第三方可通過使用 https 和 state 參數(shù),進一步加強自身授權登錄的安全性。
在這一步中,用戶先在登錄平臺進行身份校驗。
https://open.weixin.qq.com/connect/qrconnect? appid=APPID& redirect_uri=REDIRECT_URI& response_type=code& scope=SCOPE& state=STATE #wechat_redirect
參數(shù) | 是否必須 | 說明 |
---|---|---|
appid | 是 | 應用唯一標識 |
redirect_uri | 是 | 請使用 urlEncode 對鏈接進行處理 |
response_type | 是 | 填 code |
scope | 是 | 應用授權作用域,擁有多個作用域用逗號(,)分隔,網(wǎng)頁應用目前僅填寫 snsapi_login |
state | 否 | 用于保持請求和回調(diào)的狀態(tài),授權請求后原樣帶回給第三方。該參數(shù)可用于防止 csrf 攻擊(跨站請求偽造攻擊) |
注意一下 scope 是 OAuth3.0 權限控制的特點,定義了這個 code 換取的 token 可以用于什么接口。
正確配置參數(shù)后,打開這個頁面看到的是授權頁面,在用戶授權成功后,登錄平臺會帶著 code 跳轉(zhuǎn)到應用提供方指定的 redirect_uri:
redirect_uri?code=CODE&state=STATE
授權失敗時,跳轉(zhuǎn)到
redirect_uri?state=STATE
也就是失敗時沒 code。
獲取 token
在跳轉(zhuǎn)到重定向 URI 之后,應用提供方的后臺需要使用微信給你的code獲取 token,同時,你也可以用傳回來的 state 進行來源校驗。
要獲取 token,傳入正確參數(shù)訪問這個接口:
https://api.weixin.qq.com/sns/oauth3/access_token? appid=APPID& secret=SECRET& code=CODE& grant_type=authorization_code
參數(shù) | 是否必須 | 說明 |
---|---|---|
appid | 是 | 應用唯一標識,在微信開放平臺提交應用審核通過后獲得 |
secret | 是 | 應用密鑰 AppSecret,在微信開放平臺提交應用審核通過后獲得 |
code | 是 | 填寫第一步獲取的 code 參數(shù) |
grant_type | 是 | 填 authorization_code,是其中一種授權模式,微信現(xiàn)在只支持這一種 |
正確的返回:
{ "access_token": "ACCESS_TOKEN", "expires_in": 7200, "refresh_token": "REFRESH_TOKEN", "openid": "OPENID", "scope": "SCOPE", "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" }
得到 token 之后你就可以根據(jù)之前申請 code 填寫的 scope 調(diào)用接口了。
使用 token 調(diào)用微信接口
授權作用域(scope) | 接口 | 接口說明 |
---|---|---|
snsapi_base | /sns/oauth3/access_token | 通過 code 換取 access_token 、refresh_token 和已授權 scope |
snsapi_base | /sns/oauth3/refresh_token | 刷新或續(xù)期 access_token 使用 |
snsapi_base | /sns/auth | 檢查 access_token 有效性 |
snsapi_userinfo | /sns/userinfo | 獲取用戶個人信息 |
例如獲取個人信息就是 GET https://api.weixin.qq.com/sns...
注意啦,在微信 OAuth 2.0,access_token 使用 query 傳輸,而不是上面提到的 Authorization。
使用 Authorization 的例子,如 GitHub 的授權,前面的步驟基本一致,在獲取 token 后,這樣請求接口:
curl -H "Authorization: token OAUTH-TOKEN" https://api.github.com
說回微信的 userinfo 接口,返回的數(shù)據(jù)格式如下:
{ "openid": "OPENID", "nickname": "NICKNAME", "sex": 1, "province":"PROVINCE", "city":"CITY", "country":"COUNTRY", "headimgurl":"https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46", "privilege":[ "PRIVILEGE1" "PRIVILEGE2" ], "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" }
后續(xù)使用
在使用 token 獲取用戶個人信息后,你可以接著用 userinfo 接口返回的 openid,結合 session 技術實現(xiàn)在自己服務器登錄。
// 登錄 req.session.id = openid if (req.session.id) { // 已登錄 } else { // 未登錄 } // 退出 req.session.id = null // 清除 session
總結一下 OAuth3.0 的流程和重點:
為你的應用申請 ID 和 Secret
準備好重定向接口
正確傳參獲取 code <- 重要
code 傳入你的重定向接口
在重定向接口中使用 code 獲取 token <- 重要
傳入 token 使用微信接口
OAuth3.0 著重于第三方登錄和權限限制。而且 OAuth3.0 不止微信使用的這一種授權方式,其他方式可以看阮老師的OAuth 2.0 的四種方式。
其他方法
JWT 和 OAuth3.0 都是成體系的鑒權方法,不代表登錄系統(tǒng)就一定要這么復雜。
簡單登錄系統(tǒng)其實就以上面兩種 session 儲存方式為基礎就能做到。
鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術社區(qū)
使用服務器儲存 session 為基礎,可以用類似 req.session.isLogin = true 的方法標志該 session 的狀態(tài)為已登錄。
使用客戶端儲存 session 為基礎,設置 session 的過期日期和登錄人就基本能用了。
{ "exp": 1614088104313, "usr": "admin" }
(就是和 JWT 原理基本一樣,不過沒有一套體系)
鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術社區(qū)
甚至你可以使用上面的知識自己寫一個 express 的登錄系統(tǒng):
初始化一個 store,內(nèi)存、redis、數(shù)據(jù)庫都可以
在用戶身份驗證成功后,隨機生成一串哈希碼作為 token
用 set-cookie 寫到客戶端
再在服務器寫入登錄狀態(tài),以內(nèi)存為例就是在 store 中添加哈希碼作為屬性
下次請求帶著 cookie 的話檢查 cookie 帶來的 token 是否已經(jīng)寫入 store 中即可
let store = {} // 登錄成功后 store[HASH] = true cookie.set('token', HASH) // 需要鑒權的請求鐘 const hash = cookie.get('token') if (store[hash]) { // 已登錄 } else { // 未登錄 } // 退出 const hash = cookie.get('token') delete store[hash]
總結
以下列出本文重點:
cookie 是儲存 session/session id/token 的容器
cookie 設置一般通過 set-cookie 請求頭設置
session 信息可以存放在瀏覽器,也可以存放在服務器
session 存放在服務器時,以 session id 為鑰匙獲取信息
token/session/session id 三者的界限是模糊的
一般新技術使用 token,傳統(tǒng)技術使用 session id
cookie/token/session/session id 都是用于鑒權的實用技術 JWT 是瀏覽器儲存 session 的一種
JWT 常用于單點登錄(SSO)
OAuth3.0 的 token 不是由應用端頒發(fā),存在另外的授權服務器
OAuth3.0 常用于第三方應用登錄
到此,相信大家對“Cookie/Session/Token的區(qū)別有哪些”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關內(nèi)容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!