一、需求分析
如果你經常使用騰訊QQ,就會發現它的登錄有如下特點:它可以手機電腦同時在線,但是不能在兩個手機上同時登錄一個賬號,
同端互斥登錄,指的就是:像騰訊QQ一樣,在同一型別設備上只允許單地點登錄,在不同型別設備上允許同時在線,
動態演示圖:
Sa-Token 是一個輕量級 java 權限認證框架,主要解決登錄認證、權限認證、單點登錄、OAuth2、微服務網關鑒權 等一系列權限相關問題,
Gitee 開源地址:https://gitee.com/dromara/sa-token
本文將介紹在 Sa-Token 中,如何實作以下登錄策略:
- 單地登錄:指一個賬號同一時間只能在一個地方登錄,新登錄會擠掉舊登錄,也可以叫:單端登錄,
- 多地登錄:指一個賬號同一時間可以在不同地方登錄,新登錄會和舊登錄共存,也可以叫:多端登錄,
- 同端互斥登錄:在同一型別設備上只允許單地點登錄,在不同型別設備上允許同時在線,參考騰訊QQ的登錄模式:手機和電腦可以同時在線,但不能兩個手機同時在線,
與之對應的,注銷策略也將分為以下幾種:
- 單端注銷:只在呼叫退出的一端注銷,
- 全端注銷:一端注銷,全端下線,
- 同端注銷:例如將所有手機端注銷下線,PC端不受影響,
二、多地登錄
此模式較為簡單,Sa-Token 默認模式即為多地登錄模式,
1、首先引入 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
即可,
2、在用戶登錄時將賬號id寫入會話中
@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());
}
}
如上代碼,在多人登錄同一賬號時將不會對舊會話做任何處理,同一賬號可以在多個地點任意登錄,互不影響,
3、如果要全端注銷,可以呼叫 logout
方法:
// 會話注銷
@RequestMapping("logout")
public SaResult logout() {
StpUtil.logout();
return SaResult.ok("退出登錄成功");
}
呼叫如上方法注銷后,當前賬號所有端將一起下線,
4、單端注銷
如果要只注銷一端,可將組態檔中 is-share
的值配置為 false
sa-token:
is-share: false
此配置項的含義為:在多人登錄同一賬號時,是否共用一個 Token,
- 為 true 時:所有登錄共用一個 Token,
- 為 false 時:每次登錄新建一個 Token,
此值為 false 后,每次登錄都將回傳不同的 Token,與之對應的,呼叫 StpUtil.logout()
也只會注銷掉當前的 Token,其他端不受影響,
三、單地登錄
單地登錄的重點是需要改一下 yml 組態檔:
sa-token:
is-concurrent: false
is-concurrent
的含義為是否允許同一賬號并發登錄:
- 為 true 時:允許一起登錄,
- 為 false 時:新登錄擠掉舊登錄,
其它代碼與 [多地登錄] 無異,當我們在兩個瀏覽器分別登錄同一賬號時,舊會話再次訪問系統將會得到如下提示:
{
"code": 401,
"msg": "Token 已被頂下線",
"data": null
}
在 單地登錄 模式中,不存在注銷策略的問題,因為同一時間內,一個賬號最多在一個設備在線,只要呼叫注銷,就必然是全端下線,
四、同端互斥登錄
好了,終于輪到主角出場,同端互斥登錄可以讓我們像騰訊QQ
一樣,在同一型別設備上只允許單地點登錄,在不同型別設備上允許同時在線,
那么在 Sa-Token 中如何做到同端互斥登錄呢?
首先如 單地登錄
一樣,在組態檔中,將 sa-token.is-concurrent
配置為false
,然后呼叫登錄等相關介面時宣告設備標識即可:
1、指定設備標識登錄
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
2、查詢當前登錄的設備標識
StpUtil.getLoginDevice();
如果在登錄時未指定設備型別值,呼叫此方法將回傳默認值:default-device
,
3、指定設備端型別下線
業務場景舉例:在手機端控制PC端下線(手機端本身不受影響)
StpUtil.logout(10001, "PC");
4、全端下線
在呼叫 logout
方法時,不填寫具體的設備端型別,將默認控制所有端一起下線,
StpUtil.logout(10001);
以上就是 Sa-Token 框架在處理登錄問題時的各種方案,可以看出不管是簡單的多地登錄還是復雜的同端互斥登錄,在 Sa-Token 都有完善的解決方案,
參考資料
- Sa-Token 檔案:https://sa-token.cc
- Gitee 倉庫地址:https://gitee.com/dromara/sa-token
- GitHub 倉庫地址:https://github.com/dromara/sa-token
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/556870.html
標籤:其他
上一篇:Java擴展Nginx之二:編譯nginx-clojure原始碼
下一篇:返回列表