一個登錄功能也能玩出這么多花樣?sa-token帶你輕松搞定多地登錄、單地登錄、同端互斥登錄


需求場景

說起登錄,你可能會不屑一顧,還有比這更簡單的功能嗎?

獲取一下用戶提交參數 username + password 和數據庫中一比對,有記錄返回[登錄成功],無記錄返回[用戶名或密碼錯誤]

什么,就這?

當你熟練的打包、部署、啟動項目開始了一天的摸魚之后,產品經理開始坐不住了

“小順子啊,你看咱們的APP登錄能不能加一個功能,就是那種......那個......一個用戶登錄之后,能把上一個登錄的自動擠下線”

此時的你陷入了沉思,怎么讓他在登錄之后,把上一個登錄者的會話給擠下線呢?

難道說要在每次登錄之后循環一遍Session列表,找到與此用戶同賬號的會話將其注銷,聰明如你馬上想到了這種方案將會給服務器帶來巨大的性能壓力!

那怎么辦?難道要建個Map以userId做keySession做value,建立起映射關系,然后手動取出Session做上標記[已被擠下線]?

說干就干,當你擼起袖子,噼里啪啦敲好上述邏輯之后,然后測試、打包、部署、上傳一氣呵成,又開始了一天的摸魚......

然而你還是低估了產品經理的腦洞能力

“小順子,你看你寫的功能有點小問題啊,我每次一登錄,就會把其它登錄地給擠掉線啊。”

此時的你下意識反駁到: "有什么問題?這難道不就是你想要的效果嗎?"

“en....就是....咱們能不能這樣,我在手機上登錄,能不能只把別的手機上給擠下線,但是我電腦上已經登錄的不受影響”

“擠掉肯定是全部擠掉啊,怎么可能只留下你電腦端不擠掉呢?你要的功能不可能做到”

只見此時產品經理嘴角輕輕一笑,放出了大招:

“那人家騰訊QQ是怎么做到的呢?”

一句話暴擊99999+,頓時你啞口無言,是呀,騰訊QQ怎么做到這種功能的呢?一個QQ號可以在手機和電腦上同時在線,但是卻不能兩個手機同時在線

難道說在登錄時再記錄時每次登錄的設備標識?循環檢測登錄列表的設備名稱,同設備擠下線,不同設備保持登錄?

產品經理沖上咖啡,帶着勝利的微笑離開了房間,只留下一臉愁容的你,冥思苦想着實現方案……


正題

好了,說了這么多,下面進入今天的主題————sa-token,一個可以讓你輕松解決各種登錄問題的權限認證框架!

如上述場景所言,你遇到的問題不過是三個典型的登錄模型:多地登錄、單地登錄、同端互斥登錄

  • 多地登錄:指同一賬號可以在任意地點同時登錄,互不影響
  • 單地登錄:在同一時間一個賬號只能在一個地點登錄,新登錄會擠掉舊登錄者
  • 同端互斥登錄:在同一類型設備上只允許單地點登錄,在不同類型設備上允許同時在線

接下來讓我們看看使用sa-token是如何輕松處理這三種登錄問題的

多地登錄

此模式較為簡單,sa-token默認模式即為多地登錄模式

  1. 首先添加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>
  1. 在用戶登錄時將賬號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 "登錄失敗";
	}
}
  1. 新建啟動類啟動
@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有一個全面的了解

如果覺得文章寫得不錯還請大家不要吝惜為文章點個贊,您的支持是我更新的最大動力!

最后附上項目鏈接:






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM