Go項目開發(fā)實戰(zhàn) - 用戶 Token 的派發(fā)、存儲和認(rèn)證管理
從這一節(jié)開始我們來演示如何按照思路實現(xiàn)一個用戶認(rèn)證體系,本節(jié)我們主要關(guān)注用戶Token的生成、存儲以及認(rèn)證,下一節(jié)我們會專注Token的刷新、主動踢人下線和防盜檢測。
本節(jié)內(nèi)容大綱如下:
圖片
Token串的自解釋性和生成規(guī)則
我們的用戶認(rèn)證體系里有兩種Token:AccessToken以及刷新它用的RefreshToken。
圖片
無論Token信息在產(chǎn)品的服務(wù)端有哪些構(gòu)成信息,我們發(fā)放給客戶端的都是隨機(jī)的字符串,客戶端訪問服務(wù)端API時會攜帶著Token串來訪問。
Token串的生成算法多種多樣,簡單的MD5一下子,復(fù)雜的會各種加密,在我們項目中使用的則是一個兼具安全和可解釋性的Token生成算法。
為每個用戶生成的Token的算法,會用大端序的排列方式把用戶ID放到固定位置后再進(jìn)行AES加密,同時再追加一個類似salt串的隨機(jī)字符串作為前綴,把16進(jìn)制轉(zhuǎn)換成字符串后一共有40個字符。
圖片
因為生成Token時UserID放在了固定的字節(jié)位置,所以服務(wù)端拿到Token后可以解密后再把UserID取出來,這樣的話Token就具有了自解釋性,在系統(tǒng)存儲掛掉的降級處理,或者是大數(shù)據(jù)分析應(yīng)用日志、歸因用戶行為時都有一定幫助。
解析Token的代碼在教程里就不再占用篇幅了,大家訂閱加入項目后訪問下面GitHub倉庫的代碼文件可查看詳細(xì)細(xì)節(jié)。
- Token反解析出UserID的代碼實現(xiàn)
Token的生成和存儲
Token生成的流程解讀
用戶登錄授權(quán),在給用戶發(fā)放Token前,服務(wù)端會存儲三份信息用于會話管理和認(rèn)證。它們分別是AccessToken、RefreshToken 和 UserSession 的緩存信息,其緩存結(jié)構(gòu)如下:
圖片
這個我們在上一節(jié)討論過,其中UserSession是為用戶的每個登錄過的平臺單獨維護(hù)一份Session信息,根據(jù)它們的結(jié)構(gòu)特點,我們選擇對三種緩存采用以下結(jié)構(gòu):
- AccessToken、RefreshToken 緩存以各自的Token值做為緩存Key的關(guān)鍵要素,使用Redis String存儲JSON格式的Token信息
- UserSession使用UserId做為緩存Key的關(guān)鍵要素部分,使用Redis 的Hash存儲,Hash中以每個登錄平臺的Platform名為字段Key,存儲相應(yīng)用戶JSON格式的Session信息,這樣多個平臺登錄后的會話不會相互干擾。
Token生成邏輯的流程和內(nèi)部細(xì)節(jié)我用一個順序圖給大家做了梳理,還有詳細(xì)的代碼指南
圖片
項目中有完整的實現(xiàn)步驟以及Token生成、驗證的測試用例供我們邊調(diào)試代碼邊理解
Token的校驗
拿我們上面獲得的AccessToken來試驗Token的校驗,因為需要在Header中帶上Token, 需使用curl來發(fā)起請求,大家自己測試時可選擇使用POSTMAN等工具。
curl --header "Content-Type: application/json" \
--header "go-mall-token: 3d7454dd7fe557917a0c195fceebd8c786acc97e" \
http://localhost:8080/building/token-auth-test
請求的結(jié)果如下:
圖片
大家加入項目后動手實踐時可以故意把Token寫錯看一下其他效果。
總結(jié)
本節(jié)的代碼版本號為c11,版本切換操作命令如下:
git fetch --tags
git checkout tags/c11
訪問 https://github.com/go-study-lab/go-mall/compare/c10...c11 能看本章節(jié)的詳細(xì)代碼。
圖片