如果你經常使用騰訊QQ,就會發現它的登入有如下特點:它可以手機電腦同時線上,但是不能在兩個手機上同時登入一個賬號。
同端互斥登入,指的就是:像騰訊QQ一樣,在同一型別裝置上只允許單地點登入,在不同型別裝置上允許同時線上。
動態演示圖:
Sa-Token 是一個輕量級 java 許可權認證框架,主要解決登入認證、許可權認證、單點登入、OAuth2、微服務閘道器鑑權 等一系列許可權相關問題。
Gitee 開源地址:https://gitee.com/dromara/sa-token
本文將介紹在 Sa-Token 中,如何實現以下登入策略:
與之對應的,登出策略也將分為以下幾種:
此模式較為簡單,Sa-Token 預設模式即為多地登入模式。
<!-- Sa-Token 許可權認證 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.34.0</version>
</dependency>
注:如果你使用的是 SpringBoot 3.x
,只需要將 sa-token-spring-boot-starter
修改為 sa-token-spring-boot3-starter
即可。
@RestController
@RequestMapping("/user/")
public class UserController {
@RequestMapping("doLogin")
public SaResult doLogin(String username, String password) {
// 此處僅作範例模擬,真實專案需要從資料庫中查詢資料進行比對
if("zhang".equals(username) && "123456".equals(password)) {
StpUtil.login(10001);
return SaResult.ok("登入成功");
}
return SaResult.ok("登入失敗");
}
}
啟動類:
@SpringBootApplication
public class SaTokenDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SaTokenDemoApplication.class, args);
System.out.println("\n啟動成功:Sa-Roken 設定如下:" + SaManager.getConfig());
}
}
如上程式碼,在多人登入同一賬號時將不會對舊對談做任何處理,同一賬號可以在多個地點任意登入,互不影響。
logout
方法:// 對談登出
@RequestMapping("logout")
public SaResult logout() {
StpUtil.logout();
return SaResult.ok("退出登入成功");
}
呼叫如上方法登出後,當前賬號所有端將一起下線。
如果要只登出一端,可將組態檔中 is-share
的值設定為 false
sa-token:
is-share: false
此設定項的含義為:在多人登入同一賬號時,是否共用一個 Token。
此值為 false 後,每次登入都將返回不同的 Token,與之對應的,呼叫 StpUtil.logout()
也只會登出掉當前的 Token,其他端不受影響。
單地登入的重點是需要改一下 yml 組態檔:
sa-token:
is-concurrent: false
is-concurrent
的含義為是否允許同一賬號並行登入:
其它程式碼與 [多地登入] 無異,當我們在兩個瀏覽器分別登入同一賬號時,舊對談再次存取系統將會得到如下提示:
{
"code": 401,
"msg": "Token 已被頂下線",
"data": null
}
在 單地登入 模式中,不存在登出策略的問題,因為同一時間內,一個賬號最多在一個裝置線上,只要呼叫登出,就必然是全端下線。
好了,終於輪到主角出場,同端互斥登入可以讓我們像騰訊QQ
一樣,在同一型別裝置上只允許單地點登入,在不同型別裝置上允許同時線上。
那麼在 Sa-Token 中如何做到同端互斥登入呢?
首先如 單地登入
一樣,在組態檔中,將 sa-token.is-concurrent
設定為false
,然後呼叫登入等相關介面時宣告裝置標識即可:
StpUtil.login(10001, "PC");
呼叫此方法登入後,同裝置的會被頂下線(不同裝置不受影響),再次存取系統時會丟擲 NotLoginException
異常,場景值=-4
場景值 | 對應常數 | 含義說明 |
---|---|---|
-1 | NotLoginException.NOT_TOKEN | 未能從請求中讀取到 Token |
-2 | NotLoginException.INVALID_TOKEN | 已讀取到 Token,但是 Token無效 |
-3 | NotLoginException.TOKEN_TIMEOUT | 已讀取到 Token,但是 Token已經過期 |
-4 | NotLoginException.BE_REPLACED | 已讀取到 Token,但是 Token 已被頂下線 |
-5 | NotLoginException.KICK_OUT | 已讀取到 Token,但是 Token 已被踢下線 |
如果第二個引數填寫null或不填,代表將這個賬號id所有線上端踢下線,被踢出者再次存取系統時會丟擲 NotLoginException
異常,場景值=-5
StpUtil.getLoginDevice();
如果在登入時未指定裝置型別值,呼叫此方法將返回預設值:default-device
。
業務場景舉例:在手機端控制PC端下線(手機端本身不受影響)
StpUtil.logout(10001, "PC");
在呼叫 logout
方法時,不填寫具體的裝置端型別,將預設控制所有端一起下線。
StpUtil.logout(10001);
以上就是 Sa-Token 框架在處理登入問題時的各種方案,可以看出不管是簡單的多地登入還是複雜的同端互斥登入,在 Sa-Token 都有完善的解決方案。