精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

前后端接口鑒權全解Cookie/Session/Token的區別

開發 前端
本文主要解釋與請求狀態相關的術語(cookie、session、token)和幾種常見登錄的實現方式,希望大家看完本文后可以有比較清晰的理解,有感到迷惑的地方請在評論區提出。

 原文鏈接:前后端接口鑒權全解

不知不覺也寫得比較長了,一次看不完建議收藏夾!本文主要解釋與請求狀態相關的術語(cookie、session、token)和幾種常見登錄的實現方式,希望大家看完本文后可以有比較清晰的理解,有感到迷惑的地方請在評論區提出。

Cookie

眾所周知,http 是無狀態協議,瀏覽器和服務器不可能憑協議的實現辨別請求的上下文。

于是 cookie 登場,既然協議本身不能分辨鏈接,那就在請求頭部手動帶著上下文信息吧。

舉個例子,以前去旅游的時候,到了景區可能會需要存放行李,被大包小包壓著,旅游也不開心啦。在存放行李后,服務員會給你一個牌子,上面寫著你的行李放在哪個格子,離開時,你就能憑這個牌子和上面的數字成功取回行李。

cookie 做的正是這么一件事,旅客就像客戶端,寄存處就像服務器,憑著寫著數字的牌子,寄存處(服務器)就能分辨出不同旅客(客戶端)。

你會不會想到,如果牌子被偷了怎么辦,cookie 也會被偷嗎?確實會,這就是一個很常被提到的網絡安全問題——CSRF。可以在這篇文章了解關于 CSRF 的成因和應對方法。

cookie 誕生初似乎是用于電商存放用戶購物車一類的數據,但現在前端擁有兩個 storage(local、session),兩種數據庫(websql、IndexedDB),根本不愁信息存放問題,所以現在基本上 100% 都是在連接上證明客戶端的身份。例如登錄之后,服務器給你一個標志,就存在 cookie 里,之后再連接時,都會自動帶上 cookie,服務器便分清誰是誰。另外,cookie 還可以用于跟蹤一個用戶,這就產生了隱私問題,于是也就有了“禁用 cookie”這個選項(然而現在這個時代禁用 cookie 是挺麻煩的事情)。

設置方式

現實世界的例子明白了,在計算機中怎么才能設置 cookie 呢?一般來說,安全起見,cookie 都是依靠 set-cookie 頭設置,且不允許 JavaScript 設置。 

  1. Set-Cookie: <cookie-name>=<cookie-value>  
  2. Set-Cookie: <cookie-name>=<cookie-value>Expires=<date>  
  3. Set-Cookie: <cookie-name>=<cookie-value>Max-Age=<non-zero-digit>  
  4. Set-Cookie: <cookie-name>=<cookie-value>Domain=<domain-value>  
  5. Set-Cookie: <cookie-name>=<cookie-value>Path=<path-value>  
  6. Set-Cookie: <cookie-name>=<cookie-value>; Secure  
  7. Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly  
  8. Set-Cookie: <cookie-name>=<cookie-value>SameSite=Strict  
  9. Set-Cookie: <cookie-name>=<cookie-value>SameSite=Lax  
  10. Set-Cookie: <cookie-name>=<cookie-value>SameSite=None; Secure  
  11. // Multiple attributes are also possible, for example:  
  12. Set-Cookie: <cookie-name>=<cookie-value>Domain=<domain-value>; Secure; HttpOnly 

其中 <cookie-name>=<cookie-value> 這樣的 kv 對,內容隨你定,另外還有 HttpOnly、SameSite 等配置,一條 Set-Cookie 只配置一項 cookie。

 

  •  Expires 設置 cookie 的過期時間(時間戳),這個時間是客戶端時間。
  •  Max-Age 設置 cookie 的保留時長(秒數),同時存在 Expires 和 Max-Age 的話,Max-Age 優先
  •  Domain 設置生效的域名,默認就是當前域名,不包含子域名
  •  Path 設置生效路徑,/ 全匹配
  •  Secure 設置 cookie 只在 https 下發送,防止中間人攻擊
  •  HttpOnly 設置禁止 JavaScript 訪問 cookie,防止XSS
  •  SameSite 設置跨域時不攜帶 cookie,防止CSRF

Secure 和 HttpOnly 是強烈建議開啟的。SameSite 選項需要根據實際情況討論,因為 SameSite 可能會導致即使你用 CORS 解決了跨越問題,依然會因為請求沒自帶 cookie 引起一系列問題,一開始還以為是 axios 配置問題,繞了一大圈,然而根本沒關系。

其實因為 Chrome 在某一次更新后把沒設置 SameSite 默認為 Lax,你不在服務器手動把 SameSite 設置為 None 就不會自動帶 cookie 了。

發送方式

參考 MDN,cookie 的發送格式如下(其中 PHPSESSID 相關內容下面會提到): 

  1. Cookie: <cookie-list>  
  2. Cookie: name=value  
  3. Cookie: name=valuename2=value2name3=value3  
  4. Cookie: PHPSESSID=298zf09hf012fh2csrftoken=u32t4o3tb3gg43_gat=1 

在發送 cookie 時,并不會傳上面提到的配置到服務器,因為服務器在設置后就不需要關心這些信息了,只要現代瀏覽器運作正常,收到的 cookie 就是沒問題的。

Session

從 cookie 說到 session,是因為 session 才是真正的“信息”,如上面提到的,cookie 是容器,里面裝著 PHPSESSID=298zf09hf012fh2;,這就是一個 session ID。

不知道 session 和 session id 會不會讓你看得有點頭暈?

當初 session 的存在就是要為客戶端和服務器連接提供的信息,所以我將 session 理解為信息,而 session id 是獲取信息的鑰匙,通常是一串唯一的哈希碼。

接下來分析兩個 node.js express 的中間件,理解兩種 session 的實現方式。

session 信息可以儲存在客戶端,如 cookie-session,也可以儲存在服務器,如 express-session。使用 session ID 就是把 session 放在服務器里,用 cookie 里的 id 尋找服務器的信息。

客戶端儲存

對于 cookie-session 庫,比較容易理解,其實就是把所有信息加密后塞到 cookie 里。其中涉及到 cookies 庫。在設置 session 時其實就是調用 cookies.set,把信息寫到 set-cookie 里,再返回瀏覽器。換言之,取值和賦值的本質都是操作 cookie。

瀏覽器在接收到 set-cookie 頭后,會把信息寫到 cookie 里。在下次發送請求時,信息又通過 cookie 原樣帶回來,所以服務器什么東西都不用存,只負責獲取和處理 cookie 里的信息,這種實現方法不需要 session ID。

這是一段使用 cookie-session 中間件為請求添加 cookie 的代碼: 

  1. const express = require('express')  
  2. var cookieSession = require('cookie-session')  
  3. const app = express()  
  4. app.use(  
  5.   cookieSession({  
  6.     name: 'session',  
  7.     keys: [  
  8.       /* secret keys */  
  9.       'key',  
  10.     ],  
  11.     // Cookie Options  
  12.     maxAge: 24 * 60 * 60 * 1000, // 24 hours  
  13.   })  
  14.  
  15. app.get('/', function(req, res) {  
  16.   req.session.test = 'hey'  
  17.   res.json({ 
  18.     wow: 'crazy',  
  19.   })  
  20. })  
  21. app.listen(3001) 

在通過 app.use(cookieSession()) 使用中間件之前,請求是不會設置 cookie 的,添加后再訪問(并且在設置 req.session 后,若不添加 session 信息就沒必要寫、也沒內容寫到 cookie 里),就能看到服務器響應頭部新增了下面兩行,分別寫入 session 和 session.sig: 

  1. Set-Cookie: session=eyJ0ZXN0IjoiaGV5In0=; path=/; expires=Tue, 23 Feb 2021 01:07:05 GMT; httponly  
  2. 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 編碼并不是加密,這就跟明文傳輸沒啥區別,所以請不要在客戶端 session 里放用戶密碼之類的機密信息。

即使現代瀏覽器和服務器做了一些約定,例如使用 https、跨域限制、還有上面提到 cookie 的 httponly 和 sameSite 配置等,保障了 cookie 安全。但是想想,傳輸安全保障了,如果有人偷看你電腦里的 cookie,密碼又恰好存在 cookie,那就能無聲無息地偷走密碼。相反的,只放其他信息或是僅僅證明“已登錄”標志的話,只要退出一次,這個 cookie 就失效了,算是降低了潛在危險。

說回第二個值 session.sig,它是一個 27 字節的 SHA1 簽名,用以校驗 session 是否被篡改,是 cookie 安全的又一層保障。

服務器儲存

既然要儲存在服務器,那么 express-session 就需要一個容器 store,它可以是內存、redis、mongoDB 等等等等,內存應該是最快的,但是重啟程序就沒了,redis 可以作為備選,用數據庫存 session 的場景感覺不多。

express-session 的源碼沒 cookie-session 那么簡明易懂,里面有一個有點繞的問題,req.session 到底是怎么插入的?

不關注實現可以跳過這段,有興趣的話可以跟著思路看看 express-session 的源碼。

我們可以從 .session = 這個關鍵詞開始找,找到:

  •  store.generate 否決這個,容易看出這個是初始化使用的
  •  Store.prototype.createSession 這個是根據 req 和 sess 參數在 req 中設置 session 屬性,沒錯,就是你了

于是全局搜索 createSession,鎖定 index 里的 inflate (就是填充的意思)函數。

最后尋找 inflate 的調用點,是使用 sessionID 為參數的 store.get 的回調函數,一切說得通啦——

在監測到客戶端送來的 cookie 之后,可以從 cookie 獲取 sessionID,再使用 id 在 store 中獲取 session 信息,掛到 req.session,經過這個中間件,你就能順利地使用 req 中的 session。

那賦值怎么辦呢?這就和上面儲存在客戶端不同了,上面要修改客戶端 cookie 信息,但是對于儲存在服務器的情況,你修改了 session 那就是“實實在在地修改”了嘛,不用其他花里胡哨的方法,內存中的信息就是修改了,下次獲取內存里的對應信息也是修改后的信息。(僅限于內存的實現方式,使用數據庫時仍需要額外的寫入)

在請求沒有 session id 的情況下,通過 store.generate 創建新的 session,在你寫 session 的時候,cookie 可以不改變,只要根據原來的 cookie 訪問內存里的 session 信息就可以了。 

  1. var express = require('express')  
  2. var parseurl = require('parseurl')  
  3. var session = require('express-session')  
  4. var app = express()  
  5. app.use(  
  6.   session({  
  7.     secret: 'keyboard cat',  
  8.     resave: false,  
  9.     saveUninitialized: true,  
  10.   })  
  11.  
  12. app.use(function(req, res, next) {  
  13.   if (!req.session.views) {  
  14.     req.session.views = {}  
  15.   }  
  16.   // get the url pathname  
  17.   var pathname = parseurl(req).pathname  
  18.   // count the views  
  19.   req.session.views[pathname] = (req.session.views[pathname] || 0) + 1  
  20.   next()  
  21. })  
  22. app.get('/foo', function(req, res, next) {  
  23.   res.json({  
  24.     session: req.session,  
  25.   })  
  26. })   
  27. app.get('/bar', function(req, res, next) {  
  28.   res.send('you viewed this page ' + req.session.views['/bar'] + ' times')  
  29. })  
  30. app.listen(3001) 

兩種儲存方式的對比

首先還是計算機世界最重要的哲學問題:時間和空間的抉擇。

儲存在客戶端的情況,解放了服務器存放 session 的內存,但是每次都帶上一堆 base64 處理的 session 信息,如果量大的話傳輸就會很緩慢。

儲存在服務器相反,用服務器的內存拯救了帶寬。

另外,在退出登錄的實現和結果,也是有區別的。

儲存在服務器的情況就很簡單,如果 req.session.isLogin = true 是登錄,那么 req.session.isLogin = false 就是退出。

但是狀態存放在客戶端要做到真正的“即時退出登錄”就很困難了。你可以在 session 信息里加上過期日期,也可以直接依靠 cookie 的過期日期,過期之后,就當是退出了。

但是如果你不想等到 session 過期,現在就想退出登錄!怎么辦?認真想想你會發現,僅僅依靠客戶端儲存的 session 信息真的沒有辦法做到。

即使你通過 req.session = null 刪掉客戶端 cookie,那也只是刪掉了,但是如果有人曾經把 cookie 復制出來了,那他手上的 cookie 直到 session 信息里的過期時間前,都是有效的。

說“即時退出登錄”有點標題黨的意味,其實我想表達的是,你沒辦法立即廢除一個 session,這可能會造成一些隱患。

Token

session 說完了,那么出現頻率超高的關鍵字 token 又是什么?

不妨谷歌搜一下 token 這個詞,可以看到冒出來幾個(年紀大的人)比較熟悉的圖片:密碼器。過去網上銀行不是只要短信認證就能轉賬,還要經過一個密碼器,上面顯示著一個變動的密碼,在轉賬時你需要輸入密碼器中的代碼才能轉賬,這就是 token 現實世界中的例子。憑借一串碼或是一個數字證明自己身份,這事情不就和上面提到的行李問題還是一樣的嗎……

其實本質上 token 的功能就是和 session id 一模一樣。你把 session id 說成 session token 也沒什么問題(Wikipedia 里就寫了這個別名)。

其中的區別在于,session id 一般存在 cookie 里,自動帶上;token 一般是要你主動放在請求中,例如設置請求頭的 Authorization 為 bearer:<access_token>。

然而上面說的都是一般情況,根本沒有明確規定!

劇透一下,下面要講的 JWT(JSON Web Token)!他是一個 token!但是里面放著 session 信息!放在客戶端,并且可以隨你選擇放在 cookie 或是手動添加在 Authorization!但是他就叫 token!

個人覺得你不能通過存放的位置判斷是 token 或是 session id,也不能通過內容判斷是 token 或是 session 信息,session、session id 以及 token 都是很意識流的東西,只要你明白他是什么、怎么用就好了,怎么稱呼不太重要。

另外在搜索資料時也看到有些文章說 session 和 token 的區別就是新舊技術的區別,好像有點道理。

在 session 的 Wikipedia 頁面上 HTTP session token 這一欄,舉例都是 JSESSIONID (JSP)、PHPSESSID (PHP)、CGISESSID (CGI)、ASPSESSIONID (ASP) 等比較傳統的技術,就像 SESSIONID 是他們的代名詞一般;而在研究現在各種平臺的 API 接口和 OAuth2.0 登錄時,都是使用 access token 這樣的字眼,這個區別著實有點意思。

理解 session 和 token 的聯系之后,可以在哪里能看到“活的” token 呢?

打開 GitHub 進入設置,找到 Settings / Developer settings,可以看到 Personal access tokens 選項,生成新的 token 后,你就可以帶著它通過 GitHub API,證明“你就是你”。

在 OAuth 系統中也使用了 Access token 這個關鍵詞,寫過微信登錄的朋友應該都能感受到 token 是個什么啦。

Token 在權限證明上真的很重要,不可泄漏,誰拿到 token,誰就是“主人”。所以要做一個 Token 系統,刷新或刪除 Token 是必須要的,這樣在盡快彌補 token 泄漏的問題。

在理解了三個關鍵字和兩種儲存方式之后,下面我們正式開始說“用戶登錄”相關的知識和兩種登錄規范——JWT 和 OAuth2.0。

接著你可能會頻繁見到 Authentication 和 Authorization 這兩個單詞,它們都是 Auth 開頭,但可不是一個意思,簡單來說前者是驗證,后者是授權。在編寫登錄系統時,要先驗證用戶身份,設置登錄狀態,給用戶發送 token 就是授權。

JWT

全稱 JSON Web Token(RFC 7519),是的,JWT 就是一個 token。為了方便理解,提前告訴大家,JWT 用的是上面客戶端儲存的方式,所以這部分可能會經常用到上面提到的名稱。

結構

雖說 JWT 就是客戶端儲存 session 信息的一種,但是 JWT 有著自己的結構:Header.Payload.Signature(分為三個部分,用 . 隔開)

Header 

  1.  
  2.   "alg": "HS256",  
  3.   "typ": "JWT"  

typ 說明 token 類型是 JWT,alg 代表簽名算法,HMAC、SHA256、RSA 等。然后將其 base64 編碼。

Payload 

  1.  
  2.   "sub": "1234567890",  
  3.   "name": "John Doe",  
  4.   "admin": true  

Payload 是放置 session 信息的位置,最后也要將這些信息進行 base64 編碼,結果就和上面客戶端儲存的 session 信息差不多。

不過 JWT 有一些約定好的屬性,被稱為 Registered claims,包括:

  •  iss (issuer):簽發人
  •  exp (expiration time):過期時間
  •  sub (subject):主題
  •  aud (audience):受眾
  •  nbf (Not Before):生效時間
  •  iat (Issued At):簽發時間
  •  jti (JWT ID):編號

Signature

最后一部分是簽名,和上面提到的 session.sig 一樣是用于防止篡改,不過 JWT 把簽名和內容組合到一起罷了。

JWT 簽名的生成算法是這樣的: 

  1. HMACSHA256(  
  2.   base64UrlEncode(header) + "." +  
  3.   base64UrlEncode(payload),  
  4.   secret) 

使用 Header 里 alg 的算法和自己設定的密鑰 secret 編碼 base64UrlEncode(header) + "." + base64UrlEncode(payload)

最后將三部分通過 . 組合在一起,你可以通過 jwt.io Debugger 形象地看到 JWT 的組成原理:

如何使用

在驗證用戶,順利登錄后,會給用戶返回 JWT。因為 JWT 的信息沒有加密,所以別往里面放密碼,詳細原因在客戶端儲存的 cookie 中提到。

用戶訪問需要授權的連接時,可以把 token 放在 cookie,也可以在請求頭帶上 Authorization: Bearer <token>。(手動放在請求頭不受 CORS 限制,不怕 CSRF)

這樣可以用于自家登錄,也可以用于第三方登錄。單點登錄也是 JWT 的常用領域。

JWT 也因為信息儲存在客戶端造成無法讓自己失效的問題,這算是 JWT 的一個缺點。

HTTP authentication

HTTP authentication 是一種標準化的校驗方式,不會使用 cookie 和 session 相關技術。請求頭帶有 Authorization: Basic <credentials> 格式的授權字段。

其中 credentials 就是 Base64 編碼的用戶名 + : + 密碼(或 token),以后看到 Basic authentication,意識到就是每次請求都帶上用戶名密碼就好了。

Basic authentication 大概比較適合 serverless,畢竟他沒有運行著的內存,無法記錄 session,直接每次都帶上驗證就完事了。

OAuth 2.0

OAuth 2.0(RFC 6749)也是用 token 授權的一種協議,它的特點是你可以在有限范圍內使用別家接口,也可以借此使用別家的登錄系統登錄自家應用,也就是第三方應用登錄。(注意啦注意啦,OAuth 2.0 授權流程說不定面試會考哦!)

既然是第三方登錄,那除了應用本身,必定存在第三方登錄服務器。在 OAuth 2.0 中涉及三個角色:用戶、應用提供方、登錄平臺,相互調用關系如下: 

  1. +--------+                               +---------------+  
  2. |        |--(A)- Authorization Request ->|   Resource    |  
  3. |        |                               |     Owner     |  
  4. |        |<-(B)-- Authorization Grant ---|               |  
  5. |        |                               +---------------+ 
  6. |        |  
  7. |        |                               +---------------+  
  8. |        |--(C)-- Authorization Grant -->| Authorization |  
  9. | Client |                               |     Server    |  
  10. |        |<-(D)----- Access Token -------|               |  
  11. |        |                               +---------------+  
  12. |        |  
  13. |        |                               +---------------+  
  14. |        |--(E)----- Access Token ------>|    Resource   |  
  15. |        |                               |     Server    |  
  16. |        |<-(F)--- Protected Resource ---|               |  
  17. +--------+                               +---------------+ 

很多大公司都提供 OAuth 2.0 第三方登錄,這里就拿小聾哥的微信舉例吧——

準備

一般來說,應用提供方需要先在登錄平臺申請好 AppID 和 AppSecret。(微信使用這個名稱,其他平臺也差不多,一個 ID 和一個 Secret)

獲取 code

什么是授權臨時票據(code)? 答:第三方通過 code 進行獲取 access_token 的時候需要用到,code 的超時時間為 10 分鐘,一個 code 只能成功換取一次 access_token 即失效。code 的臨時性和一次保障了微信授權登錄的安全性。第三方可通過使用 https 和 state 參數,進一步加強自身授權登錄的安全性。

在這一步中,用戶先在登錄平臺進行身份校驗。 

  1. https://open.weixin.qq.com/connect/qrconnect?  
  2. appid=APPID 
  3. redirect_uri=REDIRECT_URI 
  4. response_type=code 
  5. scope=SCOPE 
  6. state=STATE  
  7. #wechat_redirect 
參數 是否必須 說明
appid 應用唯一標識
redirect_uri 請使用 urlEncode 對鏈接進行處理
response_type 填 code
scope 應用授權作用域,擁有多個作用域用逗號(,)分隔,網頁應用目前僅填寫 snsapi_login
state 用于保持請求和回調的狀態,授權請求后原樣帶回給第三方。該參數可用于防止 csrf 攻擊(跨站請求偽造攻擊)

注意一下 scope 是 OAuth2.0 權限控制的特點,定義了這個 code 換取的 token 可以用于什么接口。

正確配置參數后,打開這個頁面看到的是授權頁面,在用戶授權成功后,登錄平臺會帶著 code 跳轉到應用提供方指定的 redirect_uri: 

  1. redirect_uri?code=CODE&state=STATE 

授權失敗時,跳轉到 

  1. redirect_uri?state=STATE 

也就是失敗時沒 code。

獲取 token

在跳轉到重定向 URI 之后,應用提供方的后臺需要使用微信給你的code獲取 token,同時,你也可以用傳回來的 state 進行來源校驗。

要獲取 token,傳入正確參數訪問這個接口: 

  1. https://api.weixin.qq.com/sns/oauth2/access_token?  
  2. appid=APPID
  3. secret=SECRET 
  4. code=CODE 
  5. grant_type=authorization_code 
參數 是否必須 說明
appid 應用唯一標識,在微信開放平臺提交應用審核通過后獲得
secret 應用密鑰 AppSecret,在微信開放平臺提交應用審核通過后獲得
code 填寫第一步獲取的 code 參數
grant_type 填 authorization_code,是其中一種授權模式,微信現在只支持這一種

正確的返回: 

  1.  
  2.   "access_token": "ACCESS_TOKEN",  
  3.   "expires_in": 7200,  
  4.   "refresh_token": "REFRESH_TOKEN",  
  5.   "openid": "OPENID",  
  6.   "scope": "SCOPE",  
  7.   "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"  

得到 token 之后你就可以根據之前申請 code 填寫的 scope 調用接口了。

使用 token 調用微信接口

授權作用域(scope) 接口 接口說明
snsapi_base /sns/oauth2/access_token 通過 code 換取 access_token、refresh_token 和已授權 scope
snsapi_base /sns/oauth2/refresh_token 刷新或續期 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 后,這樣請求接口:

  1. curl -H "Authorization: token OAUTH-TOKEN" https://api.github.com 

說回微信的 userinfo 接口,返回的數據格式如下: 

  1.  
  2.   "openid": "OPENID",  
  3.   "nickname": "NICKNAME",  
  4.   "sex": 1,  
  5.   "province":"PROVINCE",  
  6.   "city":"CITY",  
  7.   "country":"COUNTRY",  
  8.   "headimgurl":"https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46", 
  9.    "privilege":[ "PRIVILEGE1" "PRIVILEGE2" ],  
  10.   "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"  

后續使用

在使用 token 獲取用戶個人信息后,你可以接著用 userinfo 接口返回的 openid,結合 session 技術實現在自己服務器登錄。 

  1. // 登錄  
  2. req.session.id = openid  
  3. if (req.session.id) {  
  4.   //   已登錄  
  5. } else {  
  6.   //   未登錄  
  7.  
  8. // 退出  
  9. req.session.id = null  
  10. // 清除 session 

總結一下 OAuth2.0 的流程和重點:

  •  為你的應用申請 ID 和 Secret
  •  準備好重定向接口
  •  正確傳參獲取 code <- 重要
  •  code 傳入你的重定向接口
  •  在重定向接口中使用 code 獲取 token <- 重要
  •  傳入 token 使用微信接口

OAuth2.0 著重于第三方登錄和權限限制。而且 OAuth2.0 不止微信使用的這一種授權方式,其他方式可以看阮老師的OAuth 2.0 的四種方式

其他方法

JWT 和 OAuth2.0 都是成體系的鑒權方法,不代表登錄系統就一定要這么復雜。

簡單登錄系統其實就以上面兩種 session 儲存方式為基礎就能做到。

  1.  使用服務器儲存 session 為基礎,可以用類似 req.session.isLogin = true 的方法標志該 session 的狀態為已登錄。
  2.  使用客戶端儲存 session 為基礎,設置 session 的過期日期和登錄人就基本能用了。 
  1.  
  2.   "exp": 1614088104313,  
  3.   "usr": "admin"  

(就是和 JWT 原理基本一樣,不過沒有一套體系)

  1.  甚至你可以使用上面的知識自己寫一個 express 的登錄系統:
  •  初始化一個 store,內存、redis、數據庫都可以
  •  在用戶身份驗證成功后,隨機生成一串哈希碼作為 token
  •  用 set-cookie 寫到客戶端
  •  再在服務器寫入登錄狀態,以內存為例就是在 store 中添加哈希碼作為屬性
  •  下次請求帶著 cookie 的話檢查 cookie 帶來的 token 是否已經寫入 store 中即可 
  1. let store = {}  
  2. // 登錄成功后  
  3. store[HASH] = true  
  4. cookie.set('token', HASH)  
  5. // 需要鑒權的請求鐘  
  6. const hash = cookie.get('token')  
  7. if (store[hash]) {  
  8.   // 已登錄  
  9. } else {  
  10.   // 未登錄  
  11.   
  12. // 退出  
  13. const hash = cookie.get('token')  
  14. delete store[hash] 

總結

以下列出本文重點:

  •  cookie 是儲存 session/session id/token 的容器
  •  cookie 設置一般通過 set-cookie 請求頭設置
  •  session 信息可以存放在瀏覽器,也可以存放在服務器
  •  session 存放在服務器時,以 session id 為鑰匙獲取信息
  •  token/session/session id 三者的界限是模糊的
  •  一般新技術使用 token,傳統技術使用 session id
  •  cookie/token/session/session id 都是用于鑒權的實用技術  JWT 是瀏覽器儲存 session 的一種
  •  JWT 常用于單點登錄(SSO)
  •  OAuth2.0 的 token 不是由應用端頒發,存在另外的授權服務器
  •  OAuth2.0 常用于第三方應用登錄 

 

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2024-10-10 12:21:56

JWTSession擴展性

2021-09-01 10:15:15

前端cookiesession

2023-12-04 10:36:46

SessionCookie

2019-11-07 10:37:36

CookieSessionToken

2019-06-11 14:45:25

2021-09-05 18:26:42

2020-05-07 10:29:29

瀏覽器Sessioncookie

2023-12-11 11:29:35

2019-06-12 19:00:14

前后端分離AppJava

2019-12-06 08:17:25

SessionCookieToken

2025-08-01 09:25:30

2024-10-14 11:56:50

2014-07-10 11:34:05

2025-05-28 03:11:00

token鑒權session

2021-08-09 08:53:30

HTTP狀態化協議

2020-01-19 10:07:25

SessionTokenCookie

2025-08-26 01:00:00

Springtoken自動續期

2025-07-29 07:11:39

2012-04-12 15:42:35

2019-07-09 05:44:35

前后端分離架構接口規范
點贊
收藏

51CTO技術棧公眾號

国产91色在线|| 精品视频中文字幕| 精品丰满人妻无套内射| 亚洲色偷精品一区二区三区| 日本va欧美va瓶| 欧美激情免费在线| 性欧美一区二区| 欧美不卡在线观看| 色欧美日韩亚洲| 日本a级片在线观看| 欧美少妇另类| 国产激情一区二区三区| 日本久久精品视频| 毛片a片免费观看| 成人羞羞动漫| 精品视频在线导航| 成人在线短视频| 亚洲成人激情社区| 亚洲线精品一区二区三区| 日韩免费av一区二区三区| 亚洲爱情岛论坛永久| 日韩中文字幕区一区有砖一区| 欧美美女18p| 欧美a在线播放| 欧美大胆视频| 日韩午夜激情电影| 国产精品区在线| 成人美女视频| 亚洲18色成人| 成年人视频大全| 尤物在线视频| 国产亚洲视频系列| 激情视频一区二区| 亚洲AV无码精品自拍| 麻豆成人久久精品二区三区红| 51精品在线观看| 国产在线观看免费视频今夜| 欧美疯狂party性派对| 亚洲人成网站在线播| 网站免费在线观看| 国产无遮挡裸体免费久久| 欧美一区永久视频免费观看| 一起操在线视频| 欧美视频免费看| 在线一区二区视频| 黑森林福利视频导航| 免费成人在线电影| 性做久久久久久免费观看欧美| 法国空姐在线观看免费| 午夜视频成人| 国产精品三级在线观看| 色一情一乱一伦一区二区三区| 日韩porn| 久久久青草青青国产亚洲免观| 九九久久99| 亚洲人午夜射精精品日韩| 99久久亚洲一区二区三区青草| 国产精品大全| 天天干天天插天天操| 99久久久久久99| 久久婷婷人人澡人人喊人人爽| 日本黄视频在线观看| 99久久精品国产一区二区三区| 国产一区二区不卡视频在线观看| 少妇一区二区三区四区| 国产成人精品免费在线| 丁香婷婷久久久综合精品国产| 蜜桃av鲁一鲁一鲁一鲁俄罗斯的| 国产69精品久久99不卡| 国产亚洲精品美女久久久m| 天堂av资源在线| 久久人人超碰精品| 天堂av一区二区| 麻豆tv免费在线观看| 亚洲免费视频成人| 精品人妻少妇一区二区| av资源亚洲| 欧美影片第一页| 樱花草www在线| 国产成人高清精品免费5388| 亚洲精品视频免费在线观看| 少妇av片在线观看| 亚洲一区色图| 88国产精品欧美一区二区三区| 中文字幕在线看人| 免费观看一级特黄欧美大片| 91精品在线影院| 欧美 日韩 国产 在线| 91香蕉视频在线| 一本色道久久综合亚洲精品婷婷| 日本资源在线| 日韩欧美极品在线观看| 亚洲小视频网站| 欧美黑人巨大videos精品| 一区二区三区天堂av| 久久久久久久久久久久久久久久久| 一本色道88久久加勒比精品| 国产久一一精品| 天堂网av在线播放| 国产精品乱码人人做人人爱| 国内精品在线观看视频| 国产精品久久久久久妇女| 精品国产91亚洲一区二区三区婷婷| 搡老熟女老女人一区二区| 国产精品99一区二区三| 欧美一级淫片丝袜脚交| 国产农村老头老太视频| 久久久影院官网| 成人在线观看www| 日韩漫画puputoon| 精品福利在线导航| 91大神福利视频| 免费一区视频| 国产精品久久久久久久小唯西川 | 成人免费看片'免费看| 国模套图日韩精品一区二区| 日韩欧美在线网站| 男人的天堂官网 | 99sesese| 免费不卡中文字幕在线| 欧美激情网友自拍| 97超碰国产在线| 国产精品婷婷午夜在线观看| 91传媒久久久| 动漫av一区| 欧美精品亚州精品| 国产一区二区三区在线观看 | 日韩免费高清av| 日本午夜精品视频| 首页国产欧美久久| 国产精品免费一区二区三区四区 | 欧美在线视频免费观看| 好吊色一区二区| 一区二区在线观看不卡| 中国黄色片一级| 色综合咪咪久久网| 国产精品日韩久久久久| 欧美理论在线观看| 精品久久久久久中文字幕一区奶水 | 欧美aaa免费| 日韩三级在线观看| 欧美日韩精品一区二区三区视频播放| 麻豆91精品91久久久的内涵| 日韩av大全| 成人免费av电影| 亚洲裸体xxxx| 狠狠狠狠狠狠狠| 国产喷白浆一区二区三区| 亚洲五月天综合| 精品国产乱码久久久久久果冻传媒 | 中文字幕一区二区三区精彩视频| 91国内外精品自在线播放| 国产午夜精品一区理论片飘花| 亚洲欧美偷拍一区| 国产日韩精品一区| 五月婷婷丁香色| 久久久久久久久久久久久久久久久久| 91精品视频在线| 日日夜夜天天综合入口| 亚洲白虎美女被爆操| 国产成人无码精品久在线观看 | 国产精品69久久久久孕妇欧美| 美女视频网站黄色亚洲| 影音先锋欧美在线| 精品国产乱码久久久久久樱花| 久久成人这里只有精品| 亚洲精品视频91| 大桥未久av一区二区三区| 一区二区黄色片| 日本91福利区| 免费的av在线| 麻豆一区二区| 国产精品av电影| 黄色成年人视频在线观看| 精品久久人人做人人爽| 欧美三级韩国三级日本三斤在线观看| 国产午夜精品美女毛片视频| 五月天av在线播放| 国产真实久久| 欧美日韩精品久久| 国产成年精品| 欧美一区二区三区免费观看| 北岛玲一区二区三区| 欧美一级一级性生活免费录像| 日本一二三区不卡| 国产女同性恋一区二区| 色悠悠在线视频| 日产国产高清一区二区三区| 三级在线免费观看| 蜜臀91精品国产高清在线观看| 成人免费淫片视频软件| 多野结衣av一区| 日韩一级黄色av| 香港三日本三级少妇66| 777a∨成人精品桃花网| 性无码专区无码| 亚洲色图制服丝袜| 亚洲熟妇无码av| 国产精品一二三| 青青草av网站| 99视频在线精品国自产拍免费观看| 五月天婷亚洲天综合网鲁鲁鲁| 一区二区三区亚洲变态调教大结局| 日韩av免费在线播放| 色噜噜狠狠狠综合欧洲色8| 中文字幕成人在线| 天堂网2014av| 日韩一区二区免费电影| 中文字幕一区二区三区四区欧美| 亚洲国产成人va在线观看天堂| 黑人と日本人の交わりビデオ| 99精品在线免费| 一级黄色大片免费看| 奇米在线7777在线精品| 亚洲欧洲日产国码无码久久99| 51精产品一区一区三区| 人偷久久久久久久偷女厕| 久久91在线| av成人在线电影| 疯狂欧洲av久久成人av电影| 国产精品igao视频| 碰碰在线视频| 久久免费视频在线观看| 伊人在我在线看导航| 日韩一区二区精品视频| 搞黄视频在线观看| 亚洲女同性videos| 亚洲 另类 春色 国产| 精品少妇一区二区三区免费观看 | 激情综合色综合久久| 男女视频一区二区三区| 国产精品永久| 成年人午夜视频在线观看| 黄色另类av| 日本大片免费看| 亚洲性人人天天夜夜摸| 激情五月六月婷婷| 亚州av乱码久久精品蜜桃| 亚洲精品国产一区| 日韩成人a**站| 亚洲欧洲国产日韩精品| 91视频精品| 致1999电视剧免费观看策驰影院| 日韩中文欧美| 黄色www在线观看| 亚洲欧美网站在线观看| av中文字幕av| 亚洲小说欧美另类社区| 黄色一级视频片| 国产日韩高清一区二区三区在线| 妞干网在线视频观看| 一本色道久久| 国产aaa一级片| 久久久久91| 黄色aaa级片| 久久成人久久爱| 精品国产鲁一鲁一区二区三区| 久久er99精品| 成人三级做爰av| 成人高清视频在线观看| 黄色录像a级片| 久久久99久久| 91ts人妖另类精品系列| 亚洲精品伦理在线| 国产网址在线观看| 日韩欧美在线中文字幕| 一区二区乱子伦在线播放| 欧美日韩不卡在线| av官网在线观看| 亚洲精品国偷自产在线99热| 美女毛片在线看| 久久久精品免费视频| 欧美人体视频xxxxx| 国产91|九色| 欧美一级做a| 国产精品国模大尺度私拍| 亚洲免费观看高清完整版在线观| 午夜精品一区二区三区在线观看| 亚洲草久电影| 日韩少妇内射免费播放| 久久精品999| 91九色蝌蚪porny| 亚洲国产精品高清| 欧美人妻精品一区二区三区| 欧美午夜精品久久久久久久| 91久久国语露脸精品国产高跟| 精品久久一区二区| jyzzz在线观看视频| 欧美国产精品日韩| 91精品韩国| 粉嫩av免费一区二区三区| blacked蜜桃精品一区| 欧美日韩视频免费| 日韩精品乱码av一区二区| 精产国品一二三区| 久久嫩草精品久久久精品| 夫妻性生活毛片| 色呦呦国产精品| 亚洲精品国产一区二| 中文字幕亚洲自拍| 老色鬼在线视频| 亚洲精品免费在线视频| 综合国产视频| 国产av人人夜夜澡人人爽麻豆| 麻豆精品在线播放| 中文字幕狠狠干| 一区二区三区毛片| 亚洲熟女乱色一区二区三区久久久| 亚洲精品白浆高清久久久久久| 老司机在线永久免费观看| 日本高清不卡在线| 999久久久精品一区二区| 日韩精彩视频| 精品成人一区| 超碰在线超碰在线| 国产日产欧美一区二区视频| 日韩精品成人一区| 日韩欧美综合在线| 黄视频网站在线看| 国产女人精品视频| 精品久久久久久久| 人妻熟女一二三区夜夜爱| 成人av免费观看| 国产亚洲精品久久久久久打不开| 555www色欧美视频| 免费高清完整在线观看| 国产精品福利在线观看| 欧美日韩爱爱| av网址在线观看免费| 91麻豆视频网站| 午夜精品久久久久久久久久久久久蜜桃| 欧美成人伊人久久综合网| 香蕉视频免费在线播放| 国产精品麻豆va在线播放| 国内精品视频在线观看| 免费黄色特级片| 国产亚洲综合av| 亚洲精品一区二区二区| 国产一区二区美女视频| 日韩精品影院| 热舞福利精品大尺度视频| 日韩av在线发布| 69视频在线观看免费| 91极品美女在线| av在线首页| 成人av番号网| 亚洲字幕久久| av天堂一区二区| 亚洲成a天堂v人片| 污污的视频网站在线观看| 2023亚洲男人天堂| 国产精品羞羞答答在线观看| 黄色片在线免费| 国产精品三级电影| 国产欧美一级片| 久久99热精品| 狠狠一区二区三区| 妺妺窝人体色www在线小说| 久久亚洲精品国产精品紫薇| 免费精品一区二区| 日韩中文综合网| 日韩欧美一级| 无罩大乳的熟妇正在播放| 久久人人97超碰com| 88av在线视频| 欧美激情xxxx性bbbb| 日韩成人av在线资源| 丁香婷婷激情网| 亚洲精品中文在线影院| 天堂在线视频网站| 国产精品成人av在线| 一区二区在线| 一级特黄a大片免费| 欧美性三三影院| 在线观看小视频| 欧美精品一区二区三区四区五区| 日本不卡一二三区黄网| 99视频只有精品| 日韩av影视在线| 久久精品国产精品亚洲毛片| 日韩精品免费一区| 2019国产精品| 99热这里只有精品在线观看| 午夜美女久久久久爽久久| 精品久久91| 亚洲激情 欧美| 欧美揉bbbbb揉bbbbb| ****av在线网毛片| 亚洲乱码一区二区三区三上悠亚| 粉嫩嫩av羞羞动漫久久久 | 日韩激情av在线| 国产大学生自拍| 亚洲人精选亚洲人成在线| 精品国产一级| 国产免费视频传媒| 亚洲第一综合色| 精品国产白色丝袜高跟鞋| 免费日韩av电影| 国产91丝袜在线18| 最近中文字幕在线观看视频|