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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

厉害了,教你用 Spring Boot 控制并发登录人数

發布時間:2025/3/21 javascript 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 厉害了,教你用 Spring Boot 控制并发登录人数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者:殷天文

www.jianshu.com/p/b6f5ec98d790

通常系統都會限制同一個賬號的登錄人數,多人登錄要么限制后者登錄,要么踢出前者,Spring Security 提供了這樣的功能,本文講解一下在沒有使用Security的時候如何手動實現這個功能

demo 技術選型

  • SpringBoot

  • JWT

  • Filter

  • Redis + Redisson

JWT(token)存儲在Redis中,類似 JSessionId-Session的關系,用戶登錄后每次請求在Header中攜帶jwt
如果你是使用session的話,也完全可以借鑒本文的思路,只是代碼上需要加些改動

兩種實現思路

比較時間戳

維護一個 username: jwtToken 這樣的一個 key-value 在Reids中, Filter邏輯如下

?

圖片不清可點開放大

public?class?CompareKickOutFilter?extends?KickOutFilter?{@Autowiredprivate?UserService?userService;@Overridepublic?boolean?isAccessAllowed(HttpServletRequest?request,?HttpServletResponse?response)?{String?token?=?request.getHeader("Authorization");String?username?=?JWTUtil.getUsername(token);String?userKey?=?PREFIX?+?username;RBucket<String>?bucket?=?redissonClient.getBucket(userKey);String?redisToken?=?bucket.get();if?(token.equals(redisToken))?{return?true;}?else?if?(StringUtils.isBlank(redisToken))?{bucket.set(token);}?else?{Long?redisTokenUnixTime?=?JWTUtil.getClaim(redisToken,?"createTime").asLong();Long?tokenUnixTime?=?JWTUtil.getClaim(token,?"createTime").asLong();//?token?>?redisToken?則覆蓋if?(tokenUnixTime.compareTo(redisTokenUnixTime)?>?0)?{bucket.set(token);}?else?{//?注銷當前tokenuserService.logout(token);sendJsonResponse(response,?4001,?"您的賬號已在其他設備登錄");return?false;}}return?true;} }

隊列踢出

public?class?QueueKickOutFilter?extends?KickOutFilter?{/***?踢出之前登錄的/之后登錄的用戶?默認踢出之前登錄的用戶*/private?boolean?kickoutAfter?=?false;/***?同一個帳號最大會話數?默認1*/private?int?maxSession?=?1;public?void?setKickoutAfter(boolean?kickoutAfter)?{this.kickoutAfter?=?kickoutAfter;}public?void?setMaxSession(int?maxSession)?{this.maxSession?=?maxSession;}@Overridepublic?boolean?isAccessAllowed(HttpServletRequest?request,?HttpServletResponse?response)?throws?Exception?{String?token?=?request.getHeader("Authorization");UserBO?currentSession?=?CurrentUser.get();Assert.notNull(currentSession,?"currentSession?cannot?null");String?username?=?currentSession.getUsername();String?userKey?=?PREFIX?+?"deque_"?+?username;String?lockKey?=?PREFIX_LOCK?+?username;RLock?lock?=?redissonClient.getLock(lockKey);lock.lock(2,?TimeUnit.SECONDS);try?{RDeque<String>?deque?=?redissonClient.getDeque(userKey);//?如果隊列里沒有此token,且用戶沒有被踢出;放入隊列if?(!deque.contains(token)?&&?currentSession.isKickout()?==?false)?{deque.push(token);}//?如果隊列里的sessionId數超出最大會話數,開始踢人while?(deque.size()?>?maxSession)?{String?kickoutSessionId;if?(kickoutAfter)?{?//?如果踢出后者kickoutSessionId?=?deque.removeFirst();}?else?{?//?否則踢出前者kickoutSessionId?=?deque.removeLast();}try?{RBucket<UserBO>?bucket?=?redissonClient.getBucket(kickoutSessionId);UserBO?kickoutSession?=?bucket.get();if?(kickoutSession?!=?null)?{//?設置會話的kickout屬性表示踢出了kickoutSession.setKickout(true);bucket.set(kickoutSession);}}?catch?(Exception?e)?{}}//?如果被踢出了,直接退出,重定向到踢出后的地址if?(currentSession.isKickout())?{//?會話被踢出了try?{//?注銷userService.logout(token);sendJsonResponse(response,?4001,?"您的賬號已在其他設備登錄");}?catch?(Exception?e)?{}return?false;}}?finally?{if?(lock.isHeldByCurrentThread())?{lock.unlock();LOGGER.info(Thread.currentThread().getName()?+?"?unlock");}?else?{LOGGER.info(Thread.currentThread().getName()?+?"?already?automatically?release?lock");}}return?true;}}

比較兩種方法

第一種方法邏輯簡單粗暴, 只維護一個key-value 不需要使用鎖,非要說缺點的話沒有第二種方法靈活。

第二種方法我很喜歡,代碼很優雅靈活,但是邏輯相對麻煩一些,而且為了保證線程安全地操作隊列,要使用分布式鎖。目前我們項目中使用的是第一種方法

演示

下載地址:

https://gitee.com/yintianwen7/taven-springboot-learning/tree/master/login-control

運行項目,訪問localhost:8887 demo中沒有存儲用戶信息,隨意輸入用戶名密碼,用戶名相同則被踢出

訪問 localhost:8887/index.html 彈出用戶信息, 代表當前用戶有效

另一個瀏覽器登錄相同用戶名,回到第一個瀏覽器刷新頁面,提示被踢出

application.properties中選擇開啟哪種過濾器模式,默認是比較時間戳踢出,開啟隊列踢出 queue-filter.enabled=true

總結

以上是生活随笔為你收集整理的厉害了,教你用 Spring Boot 控制并发登录人数的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 久久久人体 | av女人的天堂 | 亚洲综合一区二区 | 自拍偷拍亚洲区 | 黄色片在线免费观看 | 人体私拍套图hdxxxx | 黄色小说在线视频 | 亚洲免费av在线 | 乱lun合集小可的奶水 | 亚洲福利在线观看 | 韩国毛片视频 | 中文字幕乱码无码人妻系列蜜桃 | 91国产在线免费观看 | 看看黄色片 | 午夜性影院 | 日本免费黄色网 | 一女双乳被两男吸视频 | 一级黄色片在线 | 亚洲一区二区三区在线播放 | 欧美精选一区二区 | 黄色一级一片 | 国产不卡一 | 大尺度做爰床戏呻吟舒畅 | 亚洲成av | 中文字幕无码精品亚洲资源网久久 | 亚洲天堂首页 | 男人撒尿视频xvideos | 日本在线视频一区二区 | 377人体粉嫩噜噜噜 www.av黄色 | 日韩三级中文 | 免费黄色观看 | 国产一区二区在线免费 | 茄子爱啪啪| av巨作| 久久一道本 | 色天使在线视频 | 天堂av中文在线观看 | 2021狠狠干| 亚洲精品成人在线视频 | 国产欲妇 | 一级免费观看 | 色狠久| 成人自拍网站 | 福利姬在线观看 | 人人澡人人添 | 黄色片视频免费 | 国产女人被狂躁到高潮小说 | 久久午夜免费视频 | 欧美丝袜视频 | 久久久久成人精品无码中文字幕 | 黄视频网站在线观看 | 中文字幕久久一区 | 四虎成人影视 | 日皮毛片 | 特黄aaaaaaaaa真人毛片 | 国产精品久久久久久在线观看 | 色呦呦免费 | 亚洲自拍偷拍一区二区三区 | 白丝av| 乱精品一区字幕二区 | 国产精品久久久久久久久久久久午夜片 | 亚洲爆乳无码一区二区三区 | 亚洲片在线观看 | 老司机深夜福利视频 | 国产在线一卡二卡 | 99视频免费| 黄色在线观看免费 | 天天爽夜夜爽夜夜爽精品视频 | 在线免费看黄色片 | 黄黄视频在线观看 | 亚洲123区 | 久久毛片网 | 亚洲理论中文字幕 | 影音先锋成人资源 | 久草免费资源站 | 少妇免费直播 | 免费在线观看你懂的 | 91在线中文| 日韩视频一二三区 | 四虎国产精品永久在线国在线 | 野花社区视频在线观看 | 欧美日b片 | 红桃视频国产精品 | 九九亚洲精品 | 国产尤物网站 | 久久九九色 | 国产一区黄 | a级片在线免费观看 | 亚洲黄色成人网 | 成人福利影院 | 国产69xx| 国产孕妇孕交大片孕 | 91av观看| 亚洲中文字幕无码一区 | 精品久久国产 | 男女互操在线观看 | 亚洲天堂三区 | jizzzxxxx | 91精品一区二区三 |