Shiro 在線會(huì)話管理

2020-07-16 17:02 更新

在線會(huì)話管理

有時(shí)候需要顯示當(dāng)前在線人數(shù)、當(dāng)前在線用戶,有時(shí)候可能需要強(qiáng)制某個(gè)用戶下線等;此時(shí)就需要獲取相應(yīng)的在線用戶并進(jìn)行一些操作。

會(huì)話控制器

@RequiresPermissions("session:*")
@Controller
@RequestMapping("/sessions")
public class SessionController {
    @Autowired
    private SessionDAO sessionDAO;
    @RequestMapping()
    public String list(Model model) {
        Collection<Session> sessions =  sessionDAO.getActiveSessions();
        model.addAttribute("sessions", sessions);
        model.addAttribute("sesessionCount", sessions.size());
        return "sessions/list";
    }
    @RequestMapping("/{sessionId}/forceLogout")
    public String forceLogout(@PathVariable("sessionId") String sessionId, 
        RedirectAttributes redirectAttributes) {
        try {
            Session session = sessionDAO.readSession(sessionId);
            if(session != null) {
                session.setAttribute(
                    Constants.SESSION_FORCE_LOGOUT_KEY, Boolean.TRUE);
            }
        } catch (Exception e) {/*忽略*/}
        redirectAttributes.addFlashAttribute("msg", "強(qiáng)制退出成功!");
        return "redirect:/sessions";
    }
}
  1. list 方法:提供了展示所有在線會(huì)話列表,通過 sessionDAO.getActiveSessions() 獲取所有在線的會(huì)話。
  2. forceLogout 方法:強(qiáng)制退出某一個(gè)會(huì)話,此處只在指定會(huì)話中設(shè)置 Constants.SESSION_FORCE_LOGOUT_KEY 屬性,之后通過 ForceLogoutFilter 判斷并進(jìn)行強(qiáng)制退出。

此處展示會(huì)話列表的缺點(diǎn)是:sessionDAO.getActiveSessions() 提供了獲取所有活躍會(huì)話集合,如果做一般企業(yè)級應(yīng)用問題不大,因?yàn)樵诰€用戶不多;但是如果應(yīng)用的在線用戶非常多,此種方法就不適合了,解決方案就是分頁獲?。?/p>

Java代碼

Page<Session> getActiveSessions(int pageNumber, int pageSize); 

Page 對象除了包含 pageNumber、pageSize 屬性之外,還包含 totalSessions(總會(huì)話數(shù))、Collection (當(dāng)前頁的會(huì)話)。

分頁獲取時(shí),如果是 MySQL 這種關(guān)系數(shù)據(jù)庫存儲會(huì)話比較好辦,如果使用 Redis 這種數(shù)據(jù)庫可以考慮這樣存儲:

session.id=會(huì)話序列化數(shù)據(jù)
session.ids=會(huì)話id Set列表(接著可以使用LLEN獲取長度,LRANGE分頁獲?。?/code>

會(huì)話創(chuàng)建時(shí)(如 sessionId=123),那么 redis 命令如下所示:

SET session.123 "Session序列化數(shù)據(jù)"
LPUSH session.ids 123 

會(huì)話刪除時(shí)(如 sessionId=123),那么 redis 命令如下所示:

DEL session.123
LREM session.ids 123

獲取總活躍會(huì)話:

LLEN session.ids

分頁獲取活躍會(huì)話:

LRANGE key 0 10 #獲取到會(huì)話ID
MGET session.1 session.2……  #根據(jù)第一條命令獲取的會(huì)話ID獲取會(huì)話數(shù)據(jù)

ForceLogoutFilter

public class ForceLogoutFilter extends AccessControlFilter {  

    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {  

        Session session = getSubject(request, response).getSession(false);  

        if(session == null) {  

            return true;  

        }  

        return session.getAttribute(Constants.SESSION_FORCE_LOGOUT_KEY) == null;  

    }  

    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {  

        try {  

            getSubject(request, response).logout(); /*強(qiáng)制退出*/ 

} catch (Exception e) {/*忽略異常*/}

        String loginUrl = getLoginUrl() + (getLoginUrl().contains("?") ? "&" : "?") + "forceLogout=1";  

        WebUtils.issueRedirect(request, response, loginUrl);  

        return false;  

    }  

強(qiáng)制退出攔截器,如果用戶會(huì)話中存在 Constants.SESSION_FORCE_LOGOUT_KEY 屬性,表示被管理員強(qiáng)制退出了;然后調(diào)用 Subject.logout() 退出,且重定向到登錄頁面(自動(dòng)拼上 fourceLogout 請求參數(shù))。

登錄控制器

在 LoginController 類的 showLoginForm 方法中最后添加如下代碼:

if(req.getParameter("forceLogout") != null) {
    model.addAttribute("error", "您已經(jīng)被管理員強(qiáng)制退出,請重新登錄");
}

即如果有請求參數(shù) forceLogout 表示是管理員強(qiáng)制退出的,在界面上顯示相應(yīng)的信息。

Shiro 配置 spring-config-shiro.xml

和之前的唯一區(qū)別是在 shiroFilter 中的 filterChainDefinitions 攔截器鏈定義中添加了 forceLogout 攔截器:

/** = forceLogout,user,sysUser

測試

1、首先輸入 ?http://localhost:8080/chapter24/?  跳轉(zhuǎn)到登錄頁面輸入 admin/123456 登錄;

2、登錄成功后,點(diǎn)擊菜單的 “會(huì)話管理”,可以看到當(dāng)前在線會(huì)話列表:

3、點(diǎn)擊 “強(qiáng)制退出” 按鈕,會(huì)話相應(yīng)的用戶再點(diǎn)擊界面的話會(huì)看到如下界面,表示已經(jīng)被強(qiáng)制退出了:

另外可參考我的 ES 中的在線會(huì)話管理功能:UserOnlineController.java,其使用數(shù)據(jù)庫存儲會(huì)話,并分頁獲取在線會(huì)話。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號