需求場景
說起登錄,你可能會不屑一顧,還有比這更簡單的功能嗎?
獲取一下用戶提交參數 username
+ password
和數據庫中一比對,有記錄返回[登錄成功],無記錄返回[用戶名或密碼錯誤]
什么,就這?
當你熟練的打包、部署、啟動項目開始了一天的摸魚之后,產品經理開始坐不住了
“小順子啊,你看咱們的APP登錄能不能加一個功能,就是那種......那個......一個用戶登錄之后,能把上一個登錄的自動擠下線”
此時的你陷入了沉思,怎么讓他在登錄之后,把上一個登錄者的會話給擠下線呢?
難道說要在每次登錄之后循環一遍Session列表
,找到與此用戶同賬號的會話將其注銷,聰明如你馬上想到了這種方案將會給服務器帶來巨大的性能壓力!
那怎么辦?難道要建個Map以userId做key
、Session做value
,建立起映射關系,然后手動取出Session
做上標記[已被擠下線]?
說干就干,當你擼起袖子,噼里啪啦敲好上述邏輯之后,然后測試、打包、部署、上傳一氣呵成,又開始了一天的摸魚......
然而你還是低估了產品經理的腦洞能力
“小順子,你看你寫的功能有點小問題啊,我每次一登錄,就會把其它登錄地給擠掉線啊。”
此時的你下意識反駁到: "有什么問題?這難道不就是你想要的效果嗎?"
“en....就是....咱們能不能這樣,我在手機上登錄,能不能只把別的手機上給擠下線,但是我電腦上已經登錄的不受影響”
“擠掉肯定是全部擠掉啊,怎么可能只留下你電腦端不擠掉呢?你要的功能不可能做到”
只見此時產品經理嘴角輕輕一笑,放出了大招:
“那人家騰訊QQ是怎么做到的呢?”
一句話暴擊99999+,頓時你啞口無言,是呀,騰訊QQ
怎么做到這種功能的呢?一個QQ號可以在手機和電腦上同時在線,但是卻不能兩個手機同時在線
難道說在登錄時再記錄時每次登錄的設備標識?循環檢測登錄列表的設備名稱,同設備擠下線,不同設備保持登錄?
產品經理沖上咖啡,帶着勝利的微笑離開了房間,只留下一臉愁容的你,冥思苦想着實現方案……
正題
好了,說了這么多,下面進入今天的主題————sa-token,一個可以讓你輕松解決各種登錄問題的權限認證框架!
如上述場景所言,你遇到的問題不過是三個典型的登錄模型:多地登錄、單地登錄、同端互斥登錄
- 多地登錄:指同一賬號可以在任意地點同時登錄,互不影響
- 單地登錄:在同一時間一個賬號只能在一個地點登錄,新登錄會擠掉舊登錄者
- 同端互斥登錄:在同一類型設備上只允許單地點登錄,在不同類型設備上允許同時在線
接下來讓我們看看使用sa-token
是如何輕松處理這三種登錄問題的
多地登錄
此模式較為簡單,sa-token
默認模式即為多地登錄模式
- 首先添加
pom.xml
框架
<!-- sa-token 權限認證, 在線文檔:http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.12.1</version>
</dependency>
- 在用戶登錄時將賬號id寫入會話中
@RestController
@RequestMapping("user")
public class UserController {
@RequestMapping("doLogin")
public String doLogin(String username, String password) {
// 此處僅作示例模擬,真實項目需要從數據庫中查詢數據進行比對
if("zhang".equals(username) && "123456".equals(password)) {
StpUtil.setLoginId(10001);
return "登錄成功";
}
return "登錄失敗";
}
}
- 新建啟動類啟動
@SpringBootApplication
public class SaTokenDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SaTokenDemoApplication.class, args);
System.out.println("\n啟動成功:sa-token配置如下:" + SaTokenManager.getConfig());
}
}
至此,我們已經完成了多地點登錄的全部代碼,上述代碼在多人登錄同一賬號時將不會對舊會話做任何處理,同一賬號可以在多個地點任意登錄,互不影響
單地登錄
單地登錄
與多地登錄
唯一的差異就是, 需要改一下yml配置文件
spring:
# sa-token配置
sa-token:
allow-concurrent-login: false
配置項 allow-concurrent-login
的含義為:是否允許同一賬號並發登錄 (此值為true時允許一起登錄, 為false時新登錄擠掉舊登錄)
其它代碼與[多地登錄]無異,當我們在兩個瀏覽器分別登錄同一賬號時,舊會話再次訪問系統將會得到如下提示:
{
"code": 401,
"msg": "token已被頂下線",
"data": null,
"dataCount": null
}
同端互斥登錄
好了,終於到了最終難題,同端互斥登錄可以讓我們像騰訊QQ
一樣,在同一類型設備上只允許單地點登錄,在不同類型設備上允許同時在線
那么在sa-token
中如何做到同端互斥登錄呢?
首先如單地登錄
一樣,在配置文件中,將 allowConcurrentLogin
配置為false
,然后調用登錄等相關接口時聲明設備標識即可:
指定設備標識登錄
StpUtil.setLoginId(10001, "PC");
調用此方法登錄后,同設備的會被頂下線(不同設備不受影響),再次訪問系統時會拋出 NotLoginException
異常,場景值=-4
指定設備標識強制注銷(踢人下線)
StpUtil.logoutByLoginId(10001, "PC");
如果第二個參數填寫null或不填,代表將這個賬號id所有在線端踢下線,被踢出者再次訪問系統時會拋出 NotLoginException
異常,場景值=-5
查詢當前登錄的設備標識
StpUtil.getLoginDevice();
結尾
以上就是sa-token
框架在處理登錄問題時的各種技巧,可以看出不管是簡單的多地登錄
還是復雜的同端互斥登錄
,在sa-token
都有完成的解決方案
sa-token
是近期開源的國產優秀權限認證框架,除了各種登錄認證,sa-token
還可以輕松解決項目中的各種權限認證問題,
比如:踢人下線、自動續簽、身份臨時切換等常見業務均可以一行代碼調用實現,接下來的文章我會逐一介紹這些特性,讓大家對sa-token
有一個全面的了解
如果覺得文章寫得不錯還請大家不要吝惜為文章點個贊,您的支持是我更新的最大動力!
最后附上項目鏈接:
- 官網文檔:http://sa-token.dev33.cn/
- Gitee開源地址: https://gitee.com/sz6/sa-token
- GitHub開源地址: https://github.com/click33/sa-token