一文詳解 Sa-Token 中的 SaSession 對(duì)象

Sa-Token 是一個(gè)輕量級(jí) java 權(quán)限認(rèn)證框架愤兵,主要解決登錄認(rèn)證、權(quán)限認(rèn)證排吴、單點(diǎn)登錄秆乳、OAuth2、微服務(wù)網(wǎng)關(guān)鑒權(quán) 等一系列權(quán)限相關(guān)問(wèn)題钻哩。

Gitee 開(kāi)源地址:https://gitee.com/dromara/sa-token

本文將詳細(xì)介紹 Sa-Token 中的不同 SaSession 對(duì)象的區(qū)別屹堰,以及各種方便的存取值的方法。

一街氢、Session 是什么扯键?

Session 是會(huì)話中專(zhuān)業(yè)的數(shù)據(jù)緩存組件,通過(guò) Session 我們可以很方便的緩存一些高頻讀寫(xiě)數(shù)據(jù)珊肃,提高程序性能荣刑,例如:

// 在登錄時(shí)緩存user對(duì)象 
StpUtil.getSession().set("user", user);

// 然后我們就可以在任意處使用這個(gè)user對(duì)象
SysUser user = (SysUser) StpUtil.getSession().get("user");

在 Sa-Token 中馅笙,SaSession 分為三種,分別是:

  • User-Session: 指的是框架為每個(gè) 賬號(hào)id 分配的 SaSession厉亏。
  • Token-Session: 指的是框架為每個(gè) token 分配的 SaSession董习。
  • Custom-Session: 指的是以一個(gè) 特定的值 作為SessionId,來(lái)分配的 Session爱只。

假設(shè)三個(gè)客戶(hù)端登錄同一賬號(hào)皿淋,且配置了不共享token,那么此時(shí)的Session模型是:

session-model3.png

簡(jiǎn)而言之:

  • User-Session 以UserId為主恬试,只要token指向的UserId一致窝趣,那么對(duì)應(yīng)的Session對(duì)象就一致。
  • Token-Session 以token為主忘渔,只要token不同高帖,那么對(duì)應(yīng)的Session對(duì)象就不同缰儿。
  • Custom-Session 以特定的key為主畦粮,不同key對(duì)應(yīng)不同的Session對(duì)象,同樣的key指向同一個(gè)Session對(duì)象乖阵。

二宣赔、獲取 User-Session

有關(guān)賬號(hào)Session的API如下:

// 獲取當(dāng)前賬號(hào)id的Session (必須是登錄后才能調(diào)用)
StpUtil.getSession();

// 獲取當(dāng)前賬號(hào)id的Session, 并決定在Session尚未創(chuàng)建時(shí),是否新建并返回
StpUtil.getSession(true);

// 獲取賬號(hào)id為10001的Session
StpUtil.getSessionByLoginId(10001);

// 獲取賬號(hào)id為10001的Session, 并決定在Session尚未創(chuàng)建時(shí)瞪浸,是否新建并返回
StpUtil.getSessionByLoginId(10001, true);

// 獲取SessionId為xxxx-xxxx的Session, 在Session尚未創(chuàng)建時(shí), 返回null 
StpUtil.getSessionBySessionId("xxxx-xxxx");

三儒将、獲取 Token-Session

有關(guān)令牌Session的API如下:

// 獲取當(dāng)前 Token 的 Token-Session 對(duì)象
StpUtil.getTokenSession();

// 獲取指定 Token 的 Token-Session 對(duì)象
StpUtil.getTokenSessionByToken(token);

四、獲取自定義Session

自定義Session指的是以一個(gè)特定的值作為SessionId來(lái)分配的Session, 借助自定義Session对蒲,你可以為系統(tǒng)中的任意元素分配相應(yīng)的session

例如以商品id作為key為每個(gè)商品分配一個(gè)Session钩蚊,以便于緩存和商品相關(guān)的數(shù)據(jù),其相關(guān)API如下:

// 查詢(xún)指定key的Session是否存在
SaSessionCustomUtil.isExists("goods-10001");

// 獲取指定key的Session蹈矮,如果沒(méi)有砰逻,則新建并返回
SaSessionCustomUtil.getSessionById("goods-10001");

// 獲取指定key的Session,如果沒(méi)有泛鸟,第二個(gè)參數(shù)決定是否新建并返回  
SaSessionCustomUtil.getSessionById("goods-10001", false);   

// 刪除指定key的Session
SaSessionCustomUtil.deleteSessionById("goods-10001");

五蝠咆、在 Session 上存取值

// 寫(xiě)值 
session.set("name", "zhang"); 

// 寫(xiě)值 (只有在此key原本無(wú)值的時(shí)候才會(huì)寫(xiě)入)
session.setDefaultValue("name", "zhang");

// 取值
session.get("name");

// 取值 (指定默認(rèn)值)
session.get("name", "<defaultValue>"); 

// 取值 (若無(wú)值則執(zhí)行參數(shù)方法, 之后將結(jié)果保存到此鍵名下,并返回此結(jié)果   若有值則直接返回, 無(wú)需執(zhí)行參數(shù)方法)
session.get("name", () -> {
            return ...;
        });

// ---------- 數(shù)據(jù)類(lèi)型轉(zhuǎn)換: ----------
session.getInt("age");         // 取值 (轉(zhuǎn)int類(lèi)型)
session.getLong("age");        // 取值 (轉(zhuǎn)long類(lèi)型)
session.getString("name");     // 取值 (轉(zhuǎn)String類(lèi)型)
session.getDouble("result");   // 取值 (轉(zhuǎn)double類(lèi)型)
session.getFloat("result");    // 取值 (轉(zhuǎn)float類(lèi)型)
session.getModel("key", Student.class);     // 取值 (指定轉(zhuǎn)換類(lèi)型)
session.getModel("key", Student.class, <defaultValue>);  // 取值 (指定轉(zhuǎn)換類(lèi)型, 并指定值為Null時(shí)返回的默認(rèn)值)

// 是否含有某個(gè)key (返回true或false)
session.has("key"); 

// 刪值 
session.delete('name');          

// 清空所有值 
session.clear();                 

// 獲取此 Session 的所有key (返回Set<String>)
session.keys();      

六、其它操作

// 返回此 Session 的id 
session.getId();                          

// 返回此 Session 的創(chuàng)建時(shí)間 (時(shí)間戳) 
session.getCreateTime();                  

// 返回此 Session 會(huì)話上的底層數(shù)據(jù)對(duì)象(如果更新map里的值北滥,請(qǐng)調(diào)用session.update()方法避免產(chǎn)生臟數(shù)據(jù))
session.getDataMap();                     

// 將這個(gè) Session 從持久庫(kù)更新一下
session.update();                         

// 注銷(xiāo)此 Session 會(huì)話 (從持久庫(kù)刪除此Session)
session.logout();                         

七刚操、SaSession 環(huán)境隔離說(shuō)明

有同學(xué)經(jīng)常會(huì)把 SaSessionHttpSession 進(jìn)行混淆,例如:

@PostMapping("/resetPoints")
public void reset(HttpSession session) {
    // 在 HttpSession 上寫(xiě)入一個(gè)值 
    session.setAttribute("name", 66);
    // 在 SaSession 進(jìn)行取值
    System.out.println(StpUtil.getSession().get("name"));   // 輸出null
}

要點(diǎn):

  1. SaSessionHttpSession 沒(méi)有任何關(guān)系再芋,在HttpSession上寫(xiě)入的值菊霜,在SaSession中無(wú)法取出。
  2. HttpSession并未被框架接管济赎,在使用Sa-Token時(shí)占卧,請(qǐng)?jiān)谌魏吻闆r下均使用SaSession遗菠,不要使用HttpSession豆瘫。

八庄萎、未登錄場(chǎng)景下獲取 Token-Session

默認(rèn)場(chǎng)景下,只有登錄后才能通過(guò) StpUtil.getTokenSession() 獲取 Token-Session廊佩。

如果想要在未登錄場(chǎng)景下獲取 Token-Session 叭喜,有兩種方法:

  • 方法一:將全局配置項(xiàng) tokenSessionCheckLogin 改為 false贺拣。
  • 方法二:使用匿名 Token-Session
// 獲取當(dāng)前 Token 的匿名 Token-Session (可在未登錄情況下使用的 Token-Session)
StpUtil.getAnonTokenSession();

注意點(diǎn):如果前端沒(méi)有提交 Token ,或者提交的 Token 是一個(gè)無(wú)效 Token 的話捂蕴,框架將不會(huì)根據(jù)此 Token 創(chuàng)建 Token-Session 對(duì)象譬涡,
而是隨機(jī)一個(gè)新的 Token 值來(lái)創(chuàng)建 Token-Session 對(duì)象,此 Token 值可以通過(guò) StpUtil.getTokenValue() 獲取到啥辨。


參考資料

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末涡匀,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子溉知,更是在濱河造成了極大的恐慌陨瘩,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件级乍,死亡現(xiàn)場(chǎng)離奇詭異舌劳,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)玫荣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)甚淡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人捅厂,你說(shuō)我怎么就攤上這事贯卦。” “怎么了焙贷?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵撵割,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我盈厘,道長(zhǎng)睁枕,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任沸手,我火速辦了婚禮外遇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘契吉。我一直安慰自己跳仿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布捐晶。 她就那樣靜靜地躺著菲语,像睡著了一般妄辩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上山上,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天眼耀,我揣著相機(jī)與錄音,去河邊找鬼佩憾。 笑死哮伟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的妄帘。 我是一名探鬼主播楞黄,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼抡驼!你這毒婦竟也來(lái)了鬼廓?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤致盟,失蹤者是張志新(化名)和其女友劉穎碎税,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體勾邦,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蚣录,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年割择,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了眷篇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡荔泳,死狀恐怖蕉饼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情玛歌,我是刑警寧澤昧港,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站支子,受9級(jí)特大地震影響创肥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜值朋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一叹侄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧昨登,春花似錦趾代、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)禽捆。三九已至,卻和暖如春飘哨,著一層夾襖步出監(jiān)牢的瞬間胚想,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工芽隆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留顿仇,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓摆马,卻偏偏與公主長(zhǎng)得像臼闻,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子囤采,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容