java中如何踢人下線?封禁某個賬號後使其會話立即掉線!

省長來了發表於2021-01-19

需求場景

封禁賬號是一個比較常見的業務需求,尤其是在論壇、社群型別的專案中,當出現了違規使用者時我們需要將其賬號立即封禁。

常規的設計思路是:在設計使用者表時增加一個狀態欄位,例如:status,其值為1時代表賬號正常,其值為0時代表賬號已被封禁。

當我們需要封禁一個賬號時,只需要將其賬號的status值修改為0即可,對方再次登入系統時,我們便可以檢測到status值不為1禁止登入。

這種模式雖然思路簡單,但也有一個不小的問題,那就是: 如果對方一直線上不登出登入呢?

由於我們只在登入時檢測status值,這也就代表:如果對方不主動登出賬號,他的會話還是會一直存在且有效。

那怎麼才可以做到在封禁賬號後立即生效?

你可能會想到使用攔截器,攔截使用者的所有請求檢測賬號狀態:status=0時禁止訪問,status=1時再對請求放行

此方式雖然解決了問題,但是如果每次請求都要進行資料庫查詢的話,資料庫表示你如此掃蕩我你就沒有一點心理壓力嗎?

那怎麼辦?上快取?雖然可以緩解效能壓力,但似乎總感覺沒有完美解決問題。

真正的問題點在於:一個正常的系統只有0.01%的使用者是需要封禁的,我們對其它99.99%使用者的實時檢測都是不必要的效能浪費。

在如上場景中,我們真正需要的是一個踢人下線的操作,即:我們需要在封禁某個使用者後,使他的會話立即掉線,即時他重新登入也會被禁止登入

那麼,怎麼做到實時踢人下線呢?

筆者使用的是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. 將指定id的賬號
// 使指定id賬號的會話登出登入,對方再次訪問系統時會丟擲`NotLoginException`異常,場景值為-5
@RequestMapping("kickout")
public String kickout(long userId) {
	StpUtil.logoutByLoginId(userId);
	return "剔出成功";
}

關鍵程式碼就在 StpUtil.logoutByLoginId(userId) 這一句,使指定id的賬號登出登入 (踢人下線)

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

最後附上專案連結:





相關文章