圖解用戶登錄驗證業(yè)務(wù)流程(推薦)
前言
本文通過圖示及代碼的方式介紹用戶登錄流程及技術(shù)實現(xiàn),內(nèi)容包括用戶登錄,用戶驗證,如何獲取操作用戶的信息以及一些黑名單及匿名接口如何免驗證相關(guān)的實現(xiàn)。
結(jié)合昨天的網(wǎng)關(guān)相關(guān)知識食用更佳
業(yè)務(wù)圖解
對于用戶登錄來說、涉及到了用戶注冊、登錄驗證幾個方面,通過流程圖演示如何處理(新用戶/老用戶)登錄

流程解讀
客戶端-登錄界面(通常手機(jī)驗證碼登錄)
填寫手機(jī)號 發(fā)送驗證碼 填寫驗證碼 勾選新用戶自動注冊
服務(wù)端-用戶驗證
驗證賬號驗證碼是否正確 驗證用戶是否存在(不存在出初始化用戶信息) 完成驗證生成token 將token返回給客戶端
用戶信息設(shè)計

驗證流程圖解

登錄驗證流程涉及到了兩個接口,兩個緩存。1.獲取驗證碼接口,給手機(jī)號發(fā)送驗證碼并設(shè)置驗證碼緩存,設(shè)置過期時間;2.登錄接口,提交手機(jī)號及驗證碼,讀取緩存進(jìn)行匹配驗證,成功則生成token返回給客戶端,客戶端登錄成功,登錄后請求頭攜帶token進(jìn)行業(yè)務(wù)請求即可。
關(guān)于token過期時間
通常我們token的過期時間是根據(jù)客戶端的類型來定義的,app的過期時間會更長一些(通常一個星期),web端過期時間以小時為單位,如果控制過期時間可以將web登錄和app登錄拆分為兩個接口(能夠分流,接口壓力更?。蛘呤歉鶕?jù)請求頭信息進(jìn)行判斷即可,是移動端就設(shè)置7天,是web端就設(shè)置兩小時。
關(guān)于業(yè)務(wù)請求token驗證
登錄成功后,客戶端每次請求都會攜帶token,通常我們會有一個網(wǎng)關(guān)來進(jìn)行token驗證,網(wǎng)關(guān)用于登錄驗證的核心就是登錄成功后寫入的token作為key,值為用戶基礎(chǔ)信息的緩存,圖解如下:

驗證成功后,重寫內(nèi)部請求頭,將用戶的的id,賬號,昵稱信息放入請求頭中,這樣可以方便業(yè)務(wù)系統(tǒng)獲取當(dāng)前操作用戶信息以及權(quán)限控制等等
關(guān)于登出操作
用戶攜帶token請求登出接口,登出接口對token對應(yīng)的緩存進(jìn)行刪除操作,返回401即可,客戶端獲取到401就會跳轉(zhuǎn)到登錄頁面
關(guān)于匿名請求(免登錄)
通常匿名請求放行有兩種方案,1.授權(quán)token,為token設(shè)置單位時間內(nèi)請求次數(shù);2.配置路徑放行規(guī)則,對請求接口路徑進(jìn)行正則匹配,符合正則規(guī)則的進(jìn)行放行
方案1:授權(quán)token,限制單位時間請求次數(shù)
優(yōu)點就是雖然是免登錄接口,但是接口的操作對象可以追溯,請求次數(shù)可控,避免被非法利用;缺點就是需要更多的編碼及配置工作
技術(shù)實現(xiàn)
提供一個授權(quán)token管理頁面,主要管理token使用者,token的值,單位時間訪問次數(shù)(如每分鐘60次)
增刪改查,將授權(quán)token存放到緩存中,使用map進(jìn)行存儲,key為token,值為每分鐘訪問次數(shù)
單位時間計數(shù)緩存,過期時間為1分鐘
這時候我們需要在上面的驗證流程圖基礎(chǔ)上進(jìn)行升級

請求次數(shù)檢查代碼實現(xiàn)
import?org.springframework.beans.factory.annotation.Autowired;
import?org.springframework.data.redis.core.RedisTemplate;
import?org.springframework.stereotype.Component;
import?java.util.concurrent.TimeUnit;
/**
?*?授權(quán)token請求限制緩存
?*
?*?@author?熱黃油啤酒
?*?@since?2021-11-01
?*/
@Component
public?class?AuthTokenRequestLimitCache?{
????@Autowired
????private?RedisTemplate?redisTemplate;
????private?static?final?String?AUTH_TOKEN_LIMIT_KEY_PREFIX?=?"auth_token_limit";
????/**
?????*?請求次數(shù)+1并檢查是否超限
?????*
?????*?@param?token
?????*?@return?是否放行?
?????*/
????public?boolean?incrementWithCheck(String?token)?{
????????//?1.獲取token請求次數(shù)限制,獲取為null代表授權(quán)配置已被修改,此token已經(jīng)不具備權(quán)限
????????Integer?limit?=?getLimit(token);
????????if?(limit?==?null)?{
????????????return?false;
????????}
????????//?2.組裝緩存key,讀取緩存
????????String?key?=?String.join(":",?AUTH_TOKEN_LIMIT_KEY_PREFIX,?token);
????????Integer?count?=?redisTemplate.opsForValue().get(key);
????????//?3.沒有值代表一分鐘內(nèi)沒有請求產(chǎn)生了
????????if?(count?==?null)?{
????????????//?初始化值
????????????redisTemplate.opsForValue().increment(key);
????????????//?設(shè)置過期時間
????????????redisTemplate.expire(key,?1L,?TimeUnit.MINUTES);
????????????return?true;
????????}
????????//?自增并獲取當(dāng)前值?大于限制的話?返回false?網(wǎng)關(guān)過濾器返回提示信息(如請求過于頻繁)
????????Long?inc?=?redisTemplate.opsForValue().increment(key);
????????return?inc?<=?limit;
????}
????/**
?????*?獲取限值
?????*
?????*?@param?token
?????*?@return
?????*/
????public?Integer?getLimit(String?token)?{
????????Object?limit?=?redisTemplate.opsForHash().get("auth_token_limit",?token);
????????return?limit?==?null???null?:?(Integer)?limit;
????}
}
對于授權(quán)接口,通常是只允許get操作,對數(shù)據(jù)進(jìn)行提交或者更新是不被允許的,當(dāng)然這個是業(yè)務(wù)層面的,最終取決于系統(tǒng)設(shè)計
方案2:請求路徑正則校驗
我們在網(wǎng)關(guān)的配置文件中增加匿名接口規(guī)則,請求到網(wǎng)關(guān)時,檢查請求的路徑是否符合匿名接口規(guī)則,是則放行,不是則進(jìn)行token校驗,方案比較簡單,只需要對網(wǎng)關(guān)進(jìn)行處理即可。
關(guān)于黑名單
對于一個系統(tǒng)來說,黑名單是最后一道關(guān)卡,所以為了安全我們需要對問題用戶進(jìn)行黑名單操作,具體實現(xiàn)也比較簡單
用戶管理頁面提供一個拉黑的按鈕,拉黑后,這些用戶的id會存儲到一個set集合中去 登錄時候檢查用戶是否在黑名單中,是則拒絕登錄并提示 如果用戶已經(jīng)登錄后進(jìn)行拉黑操作,網(wǎng)關(guān)會在鑒權(quán)通過后檢查用戶是否在黑名單中,是則刪除token對應(yīng)緩存,返回401,401就會跳到登錄頁,步驟2就會進(jìn)行攔截。
總結(jié)
用戶系統(tǒng)是非?;A(chǔ)的系統(tǒng),但是很多程序員工作中可能并沒有真正的參與到用戶系統(tǒng)的開發(fā),通過此文可以對用戶登錄流程及配套功能有一個全面的了解。
感謝閱讀,希望對你有所幫助?:)?
來源:juejin.cn/post/7004756545741258765
-End-
最近有一些小伙伴,讓我?guī)兔φ乙恍?面試題?資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

面試題】即可獲取