在使用spring全家桶、Shiro鑒權(quán)框架、redis和mysql8構(gòu)建的系統(tǒng)中,出現(xiàn)了一個(gè)棘手的問題:用戶AccessToken出現(xiàn)混淆,導(dǎo)致用戶A登錄后卻獲取到用戶B的信息。這種現(xiàn)象在清除緩存后仍然頻繁發(fā)生,幾乎是百分百復(fù)現(xiàn),嚴(yán)重影響用戶體驗(yàn)。本文將針對(duì)這個(gè)問題,分析可能原因并提供解決方案。
問題描述中,開發(fā)者已經(jīng)排除了redis緩存中token重復(fù)和同一token被不同用戶使用的可能性。 uuid作為token生成方式,在百萬級(jí)用戶規(guī)模下發(fā)生碰撞的概率極低。
問題關(guān)鍵在于:為什么用戶A能夠獲取到用戶B的用戶信息?這說明系統(tǒng)在某個(gè)環(huán)節(jié)將用戶身份信息與accessToken綁定出現(xiàn)了錯(cuò)誤。 開發(fā)者懷疑Shiro框架未啟用accessToken和refreshToken機(jī)制,這可能與問題有關(guān),但并非直接原因。 accessToken和refreshToken機(jī)制主要用于實(shí)現(xiàn)token的續(xù)期和刷新,雖然能增強(qiáng)安全性,但并不能直接解決token混淆的問題。 真正的根源在于token生成和存儲(chǔ)的邏輯。
因此,問題的核心在于:如何確保每個(gè)用戶都擁有唯一的、與自身身份信息正確綁定的accessToken?
答案中給出的解決方案直擊要害:在生成并保存token之前,必須進(jìn)行驗(yàn)證,判斷該token是否已存在且已被其他用戶使用。如果檢測到?jīng)_突,則需要重新生成一個(gè)token,直到生成一個(gè)獨(dú)一無二的token為止。 這需要對(duì)token生成和存儲(chǔ)的邏輯進(jìn)行修改,在保存token之前增加一個(gè)校驗(yàn)步驟。 這個(gè)校驗(yàn)步驟可以查詢數(shù)據(jù)庫或Redis,確保新生成的token沒有被其他用戶使用。 只有通過了這個(gè)校驗(yàn),才能將token與用戶信息綁定并存儲(chǔ)。 通過這種方式,可以有效防止accessToken混淆的問題。