From 55b294abfd1d28859b706418a9e283147907c1c7 Mon Sep 17 00:00:00 2001 From: Heiky Date: Fri, 18 Dec 2020 09:59:38 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=B1=BB=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=E5=92=8C=E4=BB=A3=E7=A0=81=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/listenerr/SecuritySessionListener.java | 10 +++++----- .../common/web/session/HttpSessionContext.java | 7 ++++--- .../web/session/HttpSessionContextHolder.java | 7 ++++--- .../pearadmin/api/runner/RemoveInvalidSession.java | 14 ++++++++++---- .../java/com/pearadmin/security/BeanConfig.java | 9 ++++++++- .../security/process/SecurityLogoutHandler.java | 9 +++++++-- .../security/session/HttpSessionUtil.java | 11 +++++++++++ .../system/controller/SysLoggingController.java | 4 ---- .../system/controller/SysOnlineUserController.java | 13 ++++++++++++- 9 files changed, 61 insertions(+), 23 deletions(-) diff --git a/pear-common/src/main/java/com/pearadmin/common/web/listenerr/SecuritySessionListener.java b/pear-common/src/main/java/com/pearadmin/common/web/listenerr/SecuritySessionListener.java index 508caf49..9f0653ac 100644 --- a/pear-common/src/main/java/com/pearadmin/common/web/listenerr/SecuritySessionListener.java +++ b/pear-common/src/main/java/com/pearadmin/common/web/listenerr/SecuritySessionListener.java @@ -6,13 +6,13 @@ import javax.servlet.annotation.WebListener; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; + /** - * @Author: Heiky - * @Date: 2020/12/17 17:42 - * @Description: + * Describe: 自定义HttpSessionListener + * Author: Heiky + * CreateTime: 2020/12/17 */ - -@WebListener("自定义HttpSession监听器") +@WebListener public class SecuritySessionListener implements HttpSessionListener { private HttpSessionContext sessionContext = HttpSessionContext.getInstance(); diff --git a/pear-common/src/main/java/com/pearadmin/common/web/session/HttpSessionContext.java b/pear-common/src/main/java/com/pearadmin/common/web/session/HttpSessionContext.java index ca936c18..8c3048d5 100644 --- a/pear-common/src/main/java/com/pearadmin/common/web/session/HttpSessionContext.java +++ b/pear-common/src/main/java/com/pearadmin/common/web/session/HttpSessionContext.java @@ -4,10 +4,11 @@ import javax.servlet.http.HttpSession; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; + /** - * @Author: Heiky - * @Date: 2020/12/17 17:14 - * @Description: 单例模式 HttpSessionContext + * Describe: 单例模式 HttpSessionContext + * Author: Heiky + * CreateTime: 2020/12/17 */ public class HttpSessionContext { diff --git a/pear-common/src/main/java/com/pearadmin/common/web/session/HttpSessionContextHolder.java b/pear-common/src/main/java/com/pearadmin/common/web/session/HttpSessionContextHolder.java index 1a964e66..0ee9294f 100644 --- a/pear-common/src/main/java/com/pearadmin/common/web/session/HttpSessionContextHolder.java +++ b/pear-common/src/main/java/com/pearadmin/common/web/session/HttpSessionContextHolder.java @@ -1,9 +1,10 @@ package com.pearadmin.common.web.session; + /** - * @Author: Heiky - * @Date: 2020/12/17 17:47 - * @Description: HttpSessionContext对象持有者 + * Describe: HttpSessionContext对象持有者 + * Author: Heiky + * CreateTime: 2020/12/17 */ public class HttpSessionContextHolder { diff --git a/pear-entrance/src/main/java/com/pearadmin/api/runner/RemoveInvalidSession.java b/pear-entrance/src/main/java/com/pearadmin/api/runner/RemoveInvalidSession.java index fae342f4..1022d715 100644 --- a/pear-entrance/src/main/java/com/pearadmin/api/runner/RemoveInvalidSession.java +++ b/pear-entrance/src/main/java/com/pearadmin/api/runner/RemoveInvalidSession.java @@ -1,5 +1,6 @@ package com.pearadmin.api.runner; +import com.pearadmin.common.web.session.HttpSessionContextHolder; import com.pearadmin.system.domain.SysUser; import lombok.extern.slf4j.Slf4j; import org.activiti.engine.impl.util.CollectionUtil; @@ -9,7 +10,9 @@ import org.springframework.boot.CommandLineRunner; import org.springframework.security.core.session.SessionInformation; import org.springframework.security.core.session.SessionRegistry; import org.springframework.stereotype.Component; + import javax.annotation.Resource; +import javax.servlet.http.HttpSession; import java.time.Duration; import java.time.LocalDateTime; import java.util.List; @@ -25,8 +28,7 @@ import java.util.concurrent.TimeUnit; @Component public class RemoveInvalidSession implements CommandLineRunner { - @Resource - @Qualifier("manageSessionThreadPool") + @Resource(name = "manageSessionThreadPool") private ScheduledThreadPoolExecutor manageSessionThreadPool; @Resource @@ -38,6 +40,7 @@ public class RemoveInvalidSession implements CommandLineRunner { @Override public void run(String... args) throws Exception { manageSessionThreadPool.scheduleWithFixedDelay(() -> { + // 从sessionRegistry中获取所有的用户信息 List principals = sessionRegistry.getAllPrincipals(); for (Object principal : principals) { SysUser userDetails = (SysUser) principal; @@ -50,10 +53,13 @@ public class RemoveInvalidSession implements CommandLineRunner { List sessionInformationList = sessionRegistry.getAllSessions(userDetails, false); if (CollectionUtil.isNotEmpty(sessionInformationList)) { for (SessionInformation sessionInformation : sessionInformationList) { - // 清除已经过期的session + // 清除已经过期的session(SessionRegistry) sessionInformation.expireNow(); sessionRegistry.removeSessionInformation(sessionInformation.getSessionId()); - log.info(String.format("HttpSessionId[%s]------>已从sessionRegistry中移除", sessionInformation.getSessionId())); + log.info(String.format("HttpSessionId[%s]------>已从SessionRegistry中移除", sessionInformation.getSessionId())); + // 销毁已经过期的session + HttpSessionContextHolder.currentSessionContext().getSession(sessionInformation.getSessionId()).invalidate(); + log.info(String.format("HttpSessionId[%s]------>已从HttpSessionContext中移除", sessionInformation.getSessionId())); } } } else { diff --git a/pear-entrance/src/main/java/com/pearadmin/security/BeanConfig.java b/pear-entrance/src/main/java/com/pearadmin/security/BeanConfig.java index 1a7dc93c..9511f2ec 100644 --- a/pear-entrance/src/main/java/com/pearadmin/security/BeanConfig.java +++ b/pear-entrance/src/main/java/com/pearadmin/security/BeanConfig.java @@ -13,6 +13,7 @@ import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect; import org.thymeleaf.spring5.ISpringTemplateEngine; import org.thymeleaf.spring5.SpringTemplateEngine; import org.thymeleaf.templateresolver.ITemplateResolver; + import javax.annotation.Resource; import java.util.concurrent.ScheduledThreadPoolExecutor; @@ -20,7 +21,7 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; * Describe: Security Configuration 配置扩展 (Security Configuration 部分) * Author: Heiky * CreateTime: 2020/12/17 - * */ + */ @Configuration public class BeanConfig { @@ -68,6 +69,9 @@ public class BeanConfig { return templateEngine; } + /** + * 注册HttpSessionEventPublisher,发布HttpSessionEvent + */ @Bean public HttpSessionEventPublisher httpSessionEventPublisher() { return new HttpSessionEventPublisher(); @@ -84,6 +88,9 @@ public class BeanConfig { return new SecurityLogoutHandler(httpSessionEventPublisher); } + /** + * 注册ScheduledThreadPoolExecutor,进行在线用户用户检测,清除过期Session + */ @Bean public ScheduledThreadPoolExecutor manageSessionThreadPool() { ScheduledThreadPoolExecutor executor = diff --git a/pear-entrance/src/main/java/com/pearadmin/security/process/SecurityLogoutHandler.java b/pear-entrance/src/main/java/com/pearadmin/security/process/SecurityLogoutHandler.java index c99469ea..3c1da815 100644 --- a/pear-entrance/src/main/java/com/pearadmin/security/process/SecurityLogoutHandler.java +++ b/pear-entrance/src/main/java/com/pearadmin/security/process/SecurityLogoutHandler.java @@ -1,5 +1,6 @@ package com.pearadmin.security.process; +import com.pearadmin.common.web.session.HttpSessionContextHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.core.Authentication; @@ -18,7 +19,7 @@ import javax.servlet.http.HttpSessionEvent; * Describe: 自定义用户注销处理类 * Author: Heiky * CreateTime: 2020/12/17 - * */ + */ public class SecurityLogoutHandler implements LogoutHandler { private static final Logger log = LoggerFactory.getLogger(SecurityLogoutHandler.class); @@ -43,16 +44,20 @@ public class SecurityLogoutHandler implements LogoutHandler { if (httpSessionEventPublisher != null) { // 构建要销毁的session HttpSessionEvent sessionEvent = new HttpSessionEvent(request.getSession()); + // 发布session销毁事件 httpSessionEventPublisher.sessionDestroyed(sessionEvent); } + // 销毁session if (invalidateHttpSession) { HttpSession session = request.getSession(false); + // 移除HttpSessionContext中的session信息 + HttpSessionContextHolder.currentSessionContext().removeSession(session); if (session != null) { log.debug("Invalidating session: " + session.getId()); session.invalidate(); } } - + // 清空Authentication if (clearAuthentication) { SecurityContext context = SecurityContextHolder.getContext(); context.setAuthentication(null); diff --git a/pear-entrance/src/main/java/com/pearadmin/security/session/HttpSessionUtil.java b/pear-entrance/src/main/java/com/pearadmin/security/session/HttpSessionUtil.java index 5196f030..a46a8d4d 100644 --- a/pear-entrance/src/main/java/com/pearadmin/security/session/HttpSessionUtil.java +++ b/pear-entrance/src/main/java/com/pearadmin/security/session/HttpSessionUtil.java @@ -1,10 +1,13 @@ package com.pearadmin.security.session; +import com.pearadmin.common.web.session.HttpSessionContext; +import com.pearadmin.common.web.session.HttpSessionContextHolder; import com.pearadmin.system.domain.SysUser; import org.activiti.engine.impl.util.CollectionUtil; import org.springframework.security.core.session.SessionInformation; import org.springframework.security.core.session.SessionRegistry; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; import java.util.List; /** @@ -23,18 +26,26 @@ public class HttpSessionUtil { public static void expiredSession(HttpServletRequest request, SessionRegistry sessionRegistry) { SysUser currentUser = (SysUser) request.getSession().getAttribute("currentUser"); String sessionId = request.getSession().getId(); + // 从sessionRegistry中获取所有的用户信息 List principals = sessionRegistry.getAllPrincipals(); for (Object principal : principals) { SysUser userDetails = (SysUser) principal; + // 若sessionRegistry中的userDetails的用户名与当前用户的用户名相同 if (userDetails != null && userDetails.getUsername().equals(currentUser.getUsername())) { + // 查询用户所有的SessionInformation,包括过期session List sessionInformationList = sessionRegistry.getAllSessions(userDetails, true); if (CollectionUtil.isNotEmpty(sessionInformationList)) { for (SessionInformation sessionInformation : sessionInformationList) { + // 不处理当前用户的session if (sessionId.equals(sessionInformation.getSessionId())) { continue; } + // 从sessionRegistry中清除session信息 sessionInformation.expireNow(); sessionRegistry.removeSessionInformation(sessionInformation.getSessionId()); + // 从HttpSessionContext中清除session信息 + HttpSession httpSession = HttpSessionContextHolder.currentSessionContext().getSession(sessionInformation.getSessionId()); + HttpSessionContextHolder.currentSessionContext().removeSession(httpSession); } } } diff --git a/pear-modules/pear-system/src/main/java/com/pearadmin/system/controller/SysLoggingController.java b/pear-modules/pear-system/src/main/java/com/pearadmin/system/controller/SysLoggingController.java index 049b09e0..dbbf4f5c 100644 --- a/pear-modules/pear-system/src/main/java/com/pearadmin/system/controller/SysLoggingController.java +++ b/pear-modules/pear-system/src/main/java/com/pearadmin/system/controller/SysLoggingController.java @@ -31,10 +31,6 @@ import java.util.Map; @RequestMapping("system/logging") public class SysLoggingController extends BaseController { - - @Autowired - private ObjectMapper objectMapper; - /** * 引 入 日 志 组 件 的 日 志 服 务 */ diff --git a/pear-modules/pear-system/src/main/java/com/pearadmin/system/controller/SysOnlineUserController.java b/pear-modules/pear-system/src/main/java/com/pearadmin/system/controller/SysOnlineUserController.java index 694992c6..e00317bf 100644 --- a/pear-modules/pear-system/src/main/java/com/pearadmin/system/controller/SysOnlineUserController.java +++ b/pear-modules/pear-system/src/main/java/com/pearadmin/system/controller/SysOnlineUserController.java @@ -50,7 +50,6 @@ public class SysOnlineUserController extends BaseController { sysOnlineUser.setUsername(objs.getUsername()); sysOnlineUser.setRealName(objs.getRealName()); sysOnlineUser.setLastTime(objs.getLastTime()); - System.out.println(objs.getLastTime()); sysOnlineUser.setOnlineTime(Duration.between(objs.getLastTime(), LocalDateTime.now()).toMinutes() + "分钟"); onlineUser.add(sysOnlineUser); } @@ -58,6 +57,10 @@ public class SysOnlineUserController extends BaseController { return dataTable(onlineUser); } + /** + * Describe: 获取在线用户列表视图 + * Return: ModelAndView + */ @GetMapping("main") @PreAuthorize("hasPermission('/system/online/main','sys:online:main')") public ModelAndView main() { @@ -65,19 +68,27 @@ public class SysOnlineUserController extends BaseController { } + /** + * Describe: 踢出用户(下线) + * Param: onlineId + * Return: ModelAndView + */ @DeleteMapping("/remove/{onlineId}") @ResponseBody public Result remove(@PathVariable String onlineId) { + // 从sessionRegistry中获取所有的用户信息 List principals = sessionRegistry.getAllPrincipals(); for (Object principal : principals) { SysUser userDetails = (SysUser) principal; String userId = userDetails.getUserId(); if (onlineId.equals(userId)) { + // 不允许操作admin用户下线 if ("admin".equals(userDetails.getUsername())) { return failure("不允许操作超级管理员[admin]下线"); } for (SessionInformation sessionInformation : sessionRegistry.getAllSessions(userDetails, false)) { sessionInformation.expireNow(); + // 从sessionRegistry中清除session信息 sessionRegistry.removeSessionInformation(sessionInformation.getSessionId()); HttpSessionContext sessionContext = HttpSessionContextHolder.currentSessionContext(); // 销毁session -- Gitee