今天在公司加班,突然心血來潮想看看公司一款產品的後管平臺登錄圖片驗證碼是如何實現的,發現用的方案就是session。首先加載頁面時去得到驗證碼,後臺將驗證碼數字存入到session中,然後在登陸時把前端傳入的驗證碼數字同後臺取出的碼進行比較,比較之前首先把原來的session移除掉。若相同則驗證通過,不同則驗證不通過然後重新請求。這個流程本來是沒有什麼問題的,然而自己突然想到這裡會不會有點問題呢?session在並發時會不會出現覆蓋的情況呢?然後就動手開始測試。
首先,使用谷歌瀏覽器在登陸頁面A複製一個登陸頁面B出來,此時就出現問題了,由於B頁面的出現原先的session值已經被覆蓋掉了,此時A頁面輸入驗證碼後就會提示驗證碼錯誤。此時就在想能不能通過新的方案來解決這個問題。既然覆蓋的原因是因為session的key相同造成的,那我能不能使用不同的key,那不就行了嗎?這時很自然的想到了使用cookie,用cookie來保存一個隨機數,每次請求驗證碼時候設置一個隨機數存入cookie,同時session的key就是用這個隨機數,並給cookie設置了個過期時間。由於cookie可以覆蓋,所以不用擔心同一時間,大量的請求問題。
代碼完成後,便開始測試,然而並不是想的那麼順利,此時出現了一個困擾了我幾個小時的問題。每次瀏覽器請求時都被寫入cookie,可為什麼在登陸時就不帶上cookie呢?查了各種資料,甚至在java後臺那裡把請求頭no-cache注釋掉,都沒解決。都快要放棄時,然後突然發現,JSSESSIONID的路徑為什麼和COOKIE的路徑不一樣呢?然後查了一些路徑方面的資料,終於發現是這個原因了。然後再試試問題就解決了,真是坑了我好久。
然後我又突然想到,session是線程安全的嗎,會不會存在著覆蓋的情況。仔細分析後發現是安全的,我同時打開谷歌、火狐瀏覽器,然後使用不同的用戶登錄系統,發現並沒有出現session裡用戶名被覆蓋的情況,原因原來是JSSESSION這個東西,JSSESSIONID表示一個會話,這個會話維護著自己的session,所以不會出現覆蓋的情況。這同時也解釋了為什麼我最初時也就是沒有改驗證碼情況之前,通過兩個瀏覽器不會出現驗證碼被覆蓋的情況。如果通過同一個瀏覽器來登陸不同用戶的話,就會出現用戶被覆蓋的情況,相比原因大家也都知道,那就是JSSESSIONID是一致造成的。
用了將近一天的時間弄明白了這個問題,同時也對session和cookie的原理有了更加深入的了解。學習技術就應該孜孜不倦,任何異常的產生都是有原因的,解決這個異常的過程雖然很艱難,但是隨著不斷地深入你會學到很多很多。