日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Shiro并发登录人数控制遇到的问题和解决

發布時間:2025/3/11 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Shiro并发登录人数控制遇到的问题和解决 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

shiro并發登錄人數控制遇到的問題和解決

    • 問題1:KickoutSessionControlFilter不起作用
    • 問題2:KickoutSessionControlFilter中cache為null空指針異常
    • 問題3:服務器重啟后首頁訪問:subject.getPrincipal()報ClassCastException異常
    • 系統環境
    • 參考資料

問題1:KickoutSessionControlFilter不起作用

public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {}中設置:
{

filters.put(“kickout”, new KickoutSessionControlFilter());

filterMap.put("/**", “kickout”);
}
結果:KickoutSessionControlFilter不起作用。
進一步查看代碼:

public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {ShiroPermsFilterFactoryBean shiroFilter = new ShiroPermsFilterFactoryBean();...Map<String, Filter> filters = new HashMap<>(3);filters.put("kickout", new KickoutSessionControlFilter());shiroFilter.setFilters(filters);Map<String, String> filterMap = new LinkedHashMap<>(16);...filterMap.put("/**", "kickout");shiroFilter.setFilterChainDefinitionMap(filterMap);return shiroFilter;}

查看代碼行:shiroFilter.setFilterChainDefinitionMap(filterMap);

setFilterChainDefinitionMap點進去:

public void setFilterChainDefinitionMap(Map<String, String> filterChainDefinitionMap) {...filterChainDefinitionMap.put("/**", "user");super.setFilterChainDefinitionMap(filterChainDefinitionMap);... }

分析:

filterMap.put("/**", "kickout");

filterChainDefinitionMap.put("/**", "user");

操作的是同一個對象,
filterChainDefinitionMap是一個Map,
key一樣,put會覆蓋掉前面的值。

解決:

filterChainDefinitionMap.put("/**", "kickout,user");

問題2:KickoutSessionControlFilter中cache為null空指針異常

public class KickoutSessionControlFilter extends AccessControlFilter {private Cache<String, Deque<Serializable>> cache;...@Overrideprotected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {...Deque<Serializable> deque = cache.get(username);...deque = new LinkedList<Serializable>();cache.put(username, deque);...} }

查看:ShiroConfig.java中session管理器SessionManager

@Beanpublic SessionManager sessionManager(GlobalProperties globalProperties){DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();sessionManager.setSessionValidationSchedulerEnabled(true);sessionManager.setSessionIdUrlRewritingEnabled(false);sessionManager.setDeleteInvalidSessions(true);if (globalProperties.isRedisSessionDao()) {// 開啟redis會話管理器sessionManager.setSessionFactory(new UserSessionFactory());sessionManager.setSessionDAO(new UserSessionDAO());List<SessionListener> sessionListeners = new ArrayList<>();sessionListeners.add(new UserSessionListener());sessionManager.setSessionListeners(sessionListeners);}return sessionManager;}

發現:框架沒有配置CacheManager,有配置redis會話管理,改用RedisCacheManager。
解決:

public class KickoutSessionControlFilter extends AccessControlFilter {private Cache<String, Deque<Serializable>> cache;...@Overrideprotected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {...RedisCacheManager redisCacheManager = (RedisCacheManager) SpringContextUtils.getBean("redisCacheManager");...LinkedList<Serializable> linkedList = new LinkedList<Serializable>();...linkedList = (LinkedList<Serializable>) redisCacheManager.get(username);...redisCacheManager.set(username,linkedList);...} }

問題3:服務器重啟后首頁訪問:subject.getPrincipal()報ClassCastException異常

@Overrideprotected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {Subject subject = getSubject(request, response);if(!subject.isAuthenticated() && !subject.isRemembered()) {//如果沒有登錄,直接進行之后的流程return true;}Session session = subject.getSession();SysUserEntity user = (SysUserEntity) subject.getPrincipal();username= user.getUsername();... }

一番打端點分析:
用戶登陸狀態下,服務器重啟后:

subject.isAuthenticated()仍然為true。“//如果沒有登錄,直接進行之后的流程”該步驟不能進入,未return true,繼續后續執行。

且session仍然在,未失效。

(SysUserEntity) subject.getPrincipal();
強轉報異常,原因不明。

暫時解決方法:try捕獲ClassCastException時調用subject.logout();登出。定向到首頁。

try {SysUserEntity user = (SysUserEntity) subject.getPrincipal();username= user.getUsername();} catch (ClassCastException cce) {//服務器重啟后,session仍然在,但subject.getPrincipal會有強轉異常try {subject.logout();} catch (Exception e) { //ignore}saveRequest(request);httpServletRequest.setAttribute("errorMsg", "登錄超時,請重新登錄");httpServletRequest.getRequestDispatcher("/login").forward(request, response);return false;}

系統環境

springboot

參考資料

https://blog.csdn.net/qq_33556185/article/details/51744004
https://www.w3cschool.cn/shiro/epht1ifg.html

總結

以上是生活随笔為你收集整理的Shiro并发登录人数控制遇到的问题和解决的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。