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 new file mode 100644 index 0000000000000000000000000000000000000000..b6e8111f4989d860eac74d8c07bf6b8022c07036 --- /dev/null +++ b/pear-entrance/src/main/java/com/pearadmin/api/runner/RemoveInvalidSession.java @@ -0,0 +1,67 @@ +package com.pearadmin.api.runner; + +import com.pearadmin.system.domain.SysUser; +import lombok.extern.slf4j.Slf4j; +import org.activiti.engine.impl.util.CollectionUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +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 java.time.Duration; +import java.time.LocalDateTime; +import java.util.List; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * @Author: Heiky + * @Date: 2020/12/17 15:34 + * @Description: + */ + +@Slf4j +@Component +public class RemoveInvalidSession implements CommandLineRunner { + + @Autowired + @Qualifier("manageSessionThreadPool") + private ScheduledThreadPoolExecutor manageSessionThreadPool; + + @Autowired + private SessionRegistry sessionRegistry; + + @Value("${server.servlet.session.timeout}") + private Duration duration; + + @Override + public void run(String... args) throws Exception { + manageSessionThreadPool.scheduleWithFixedDelay(() -> { + List principals = sessionRegistry.getAllPrincipals(); + for (Object principal : principals) { + SysUser userDetails = (SysUser) principal; + // 获取用户最近一次的登录时间 + LocalDateTime lastTime = userDetails.getLastTime(); + // 获取session的目标过期时间 + LocalDateTime expiredTime = lastTime.plusSeconds(duration.getSeconds()); + // 若session过期 + if (Duration.between(LocalDateTime.now(), expiredTime).toMinutes() <= 0) { + List sessionInformationList = sessionRegistry.getAllSessions(userDetails, false); + if (CollectionUtil.isNotEmpty(sessionInformationList)) { + for (SessionInformation sessionInformation : sessionInformationList) { + // 清除已经过期的session + sessionInformation.expireNow(); + sessionRegistry.removeSessionInformation(sessionInformation.getSessionId()); + log.info(String.format("HttpSessionId[%s]------>已从sessionRegistry中移除", sessionInformation.getSessionId())); + } + } + } else { + log.info("目前sessionRegistry中,没有已经过期的httpSession"); + } + } + }, 60, 10, TimeUnit.SECONDS); + } +} diff --git a/pear-entrance/src/main/java/com/pearadmin/security/BeanConfig.java b/pear-entrance/src/main/java/com/pearadmin/security/BeanConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..93aa53b04918ed908b04e6a8c5cacea3d2b2ba09 --- /dev/null +++ b/pear-entrance/src/main/java/com/pearadmin/security/BeanConfig.java @@ -0,0 +1,102 @@ +package com.pearadmin.security; + +import com.pearadmin.security.process.SecurityLogoutHandler; +import com.pearadmin.security.support.SecurityPermissionEvaluator; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.core.session.SessionRegistry; +import org.springframework.security.core.session.SessionRegistryImpl; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler; +import org.springframework.security.web.session.HttpSessionEventPublisher; +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; + +/** + * @Author: Heiky + * @Date: 2020/12/17 10:55 + * @Description: + */ + +@Configuration +public class BeanConfig { + + /** + * 注解权限 + */ + @Resource + private SecurityPermissionEvaluator securityPermissionEvaluator; + + + /** + * Describe: 自定义权限注解实现 + */ + @Bean + public DefaultWebSecurityExpressionHandler userSecurityExpressionHandler() { + DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler(); + handler.setPermissionEvaluator(securityPermissionEvaluator); + return handler; + } + + /** + * Describe: 加密方式 + */ + @Bean + public BCryptPasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + /** + * 注册SessionRegistry + */ + @Bean + public SessionRegistry sessionRegistry() { + return new SessionRegistryImpl(); + } + + /** + * thymeleaf security 别名注册,方便前端使用 + */ + @Bean + public ISpringTemplateEngine templateEngine(ITemplateResolver templateResolver) { + SpringTemplateEngine templateEngine = new SpringTemplateEngine(); + templateEngine.setTemplateResolver(templateResolver); + templateEngine.setEnableSpringELCompiler(true); + templateEngine.addDialect(new SpringSecurityDialect()); + return templateEngine; + } + + @Bean + public HttpSessionEventPublisher httpSessionEventPublisher() { + return new HttpSessionEventPublisher(); + } + + /** + * 注册自定义的LogoutHandler + * + * @param httpSessionEventPublisher + * @return SecurityLogoutHandler + */ + @Bean + public SecurityLogoutHandler securityLogoutHandler(HttpSessionEventPublisher httpSessionEventPublisher) { + return new SecurityLogoutHandler(httpSessionEventPublisher); + } + + @Bean + public ScheduledThreadPoolExecutor manageSessionThreadPool() { + ScheduledThreadPoolExecutor executor = + new ScheduledThreadPoolExecutor(1, r -> { + Thread t = new Thread(r); + t.setName("removeSession"); + // 设置为守护线程 + t.setDaemon(true); + return t; + }); + return executor; + } +} diff --git a/pear-entrance/src/main/java/com/pearadmin/security/SecurityConfiguration.java b/pear-entrance/src/main/java/com/pearadmin/security/SecurityConfiguration.java index 0c77ba4d83a78efe144105b2791302cbfbb34ca4..325c6ebd9e0c4b255ee3ac0cef5fb5b0bedfb8df 100644 --- a/pear-entrance/src/main/java/com/pearadmin/security/SecurityConfiguration.java +++ b/pear-entrance/src/main/java/com/pearadmin/security/SecurityConfiguration.java @@ -2,12 +2,10 @@ package com.pearadmin.security; import com.pearadmin.common.config.proprety.SecurityProperty; import com.pearadmin.security.domain.SecurityUserDetailsService; -import com.pearadmin.security.process.*; import com.pearadmin.security.domain.SecurityUserTokenService; -import com.pearadmin.security.support.SecurityPermissionEvaluator; +import com.pearadmin.security.process.*; import com.pearadmin.security.support.SecurityCaptchaSupport; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; @@ -16,14 +14,8 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.session.SessionRegistry; -import org.springframework.security.core.session.SessionRegistryImpl; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -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; @@ -38,85 +30,90 @@ import javax.annotation.Resource; @EnableConfigurationProperties(SecurityProperty.class) public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + /** + * 配置未登录自定义处理类 + */ @Resource - private SecurityPermissionEvaluator securityPermissionEvaluator; //注解权限 - - @Resource - private SecurityAuthenticationEntryPoint securityAuthenticationEntryPoint; //配置未登录自定义处理类 + private SecurityAuthenticationEntryPoint securityAuthenticationEntryPoint; + /** + * 登录成功处理类 + */ @Resource - private SecurityAuthenticationSuccessHandler securityAccessSuccessHander; //登录成功处理类 + private SecurityAuthenticationSuccessHandler securityAccessSuccessHander; + /** + * 登录失败处理类 + */ @Resource - private SecurityAuthenticationFailureHandler securityAccessFailureHander; //登录失败处理类 + private SecurityAuthenticationFailureHandler securityAccessFailureHander; + /** + * 退出登录处理类 + */ @Resource - private SecurityLogoutSuccessHandler securityAccessLogoutHander; //退出登录处理类 + private SecurityLogoutSuccessHandler securityAccessLogoutHander; + /** + * 没有权限处理类 + */ @Resource - private SecurityAccessDeniedHandler securityAccessDeniedHander; //没有权限处理类 + private SecurityAccessDeniedHandler securityAccessDeniedHander; + /** + * 配置不拦截url + */ @Resource - private SecurityProperty securityProperty; //配置不拦截url + private SecurityProperty securityProperty; + /** + * 实现userservice + */ @Resource - private SecurityUserDetailsService securityUserDetailsService; //实现userservice + private SecurityUserDetailsService securityUserDetailsService; + /** + * remember me redis持久化 + */ @Resource - private SecurityUserTokenService securityUserTokenService;//remember me redis持久化 + private SecurityUserTokenService securityUserTokenService; + /** + * 自定义验证码验证 + */ @Resource - private SecurityCaptchaSupport securityCaptchaSupport; //自定义验证码验证 + private SecurityCaptchaSupport securityCaptchaSupport; @Resource private SecurityExpiredSessionHandler securityExpiredSessionHandler; - /** - * Describe: 自定义权限注解实现 + * 密码加密 */ - @Bean - public DefaultWebSecurityExpressionHandler userSecurityExpressionHandler() { - DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler(); - handler.setPermissionEvaluator(securityPermissionEvaluator); - return handler; - } + @Resource + private PasswordEncoder passwordEncoder; /** - * Describe: 加密方式 + * 用于统计用户在线 */ - @Bean - public BCryptPasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } + @Resource + private SessionRegistry sessionRegistry; + + @Resource + private SecurityLogoutHandler securityLogoutHandler; + + @Resource + private RememberMeAuthenticationSuccessHandler rememberMeAuthenticationSuccessHandler; + /** * 身份认证接口 */ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth.userDetailsService(securityUserDetailsService).passwordEncoder(passwordEncoder()); + auth.userDetailsService(securityUserDetailsService).passwordEncoder(passwordEncoder); } - /** - * 注册SessionRegistry - */ - @Bean - public SessionRegistry sessionRegistry() { - return new SessionRegistryImpl(); - } - - /** - * thymeleaf security 别名注册,方便前端使用 - */ - @Bean - public ISpringTemplateEngine templateEngine(ITemplateResolver templateResolver) { - SpringTemplateEngine templateEngine = new SpringTemplateEngine(); - templateEngine.setTemplateResolver(templateResolver); - templateEngine.setEnableSpringELCompiler(true); - templateEngine.addDialect(new SpringSecurityDialect()); - return templateEngine; - } /** * Describe: 配置 Security 控制逻辑 @@ -128,41 +125,51 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { // 其他的需要登录后才能访问 .anyRequest().authenticated() .and() - .addFilterBefore(securityCaptchaSupport, UsernamePasswordAuthenticationFilter.class)//验证码验证类 - .httpBasic() + // 验证码验证类 + .addFilterBefore(securityCaptchaSupport, UsernamePasswordAuthenticationFilter.class) + .httpBasic() .authenticationEntryPoint(securityAuthenticationEntryPoint) .and() - .formLogin() - //登录页面 + .formLogin() + // 登录页面 .loginPage("/login") - //登录接口 + // 登录接口 .loginProcessingUrl("/login") - //配置登录成功自定义处理类 + // 配置登录成功自定义处理类 .successHandler(securityAccessSuccessHander) - //配置登录失败自定义处理类 + // 配置登录失败自定义处理类 .failureHandler(securityAccessFailureHander) .and() - .logout() - .deleteCookies("JSESSIONID") //退出登录删除 cookie缓存 - .logoutSuccessHandler(securityAccessLogoutHander) //配置用户登出自定义处理类 + .logout() + .addLogoutHandler(securityLogoutHandler) + // 退出登录删除 cookie缓存 + .deleteCookies("JSESSIONID") + // 配置用户登出自定义处理类 + .logoutSuccessHandler(securityAccessLogoutHander) .and() - .exceptionHandling() - .accessDeniedHandler(securityAccessDeniedHander) //配置没有权限自定义处理类 + .exceptionHandling() + // 配置没有权限自定义处理类 + .accessDeniedHandler(securityAccessDeniedHander) .and() - .rememberMe() + .rememberMe() .rememberMeParameter("remember-me") .rememberMeCookieName("rememberme-token") + .authenticationSuccessHandler(rememberMeAuthenticationSuccessHandler) .tokenRepository(securityUserTokenService) .key(securityProperty.getRememberKey()) .and() - .sessionManagement() + .sessionManagement() .sessionFixation() .migrateSession() - .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) //在需要使用到session时才创建session - .maximumSessions(1)//同时登陆多个只保留一个 + // 在需要使用到session时才创建session + .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) + // 同时登陆多个只保留一个 + .maximumSessions(1) .maxSessionsPreventsLogin(false) - .expiredSessionStrategy(securityExpiredSessionHandler) // //踢出用户操作 - .sessionRegistry(sessionRegistry()); //用于统计在线 + // 踢出用户操作 + .expiredSessionStrategy(securityExpiredSessionHandler) + // 用于统计在线 + .sessionRegistry(sessionRegistry); // 取消跨站请求伪造防护 http.csrf().disable(); diff --git a/pear-entrance/src/main/java/com/pearadmin/security/process/RememberMeAuthenticationSuccessHandler.java b/pear-entrance/src/main/java/com/pearadmin/security/process/RememberMeAuthenticationSuccessHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..25f59b7ae88ee09bfcb2d00fcf1330fede5a5fd4 --- /dev/null +++ b/pear-entrance/src/main/java/com/pearadmin/security/process/RememberMeAuthenticationSuccessHandler.java @@ -0,0 +1,71 @@ +package com.pearadmin.security.process; + +import com.pearadmin.common.plugins.logging.domain.Logging; +import com.pearadmin.common.plugins.logging.enums.BusinessType; +import com.pearadmin.common.plugins.logging.enums.LoggingType; +import com.pearadmin.common.plugins.logging.service.LoggingService; +import com.pearadmin.common.tools.security.SecurityUtil; +import com.pearadmin.common.tools.sequence.SequenceUtil; +import com.pearadmin.security.session.HttpSessionUtil; +import com.pearadmin.system.domain.SysUser; +import com.pearadmin.system.service.ISysUserService; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.session.SessionRegistry; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.time.LocalDateTime; + +/** + * @Author: Heiky + * @Date: 2020/12/17 10:38 + * @Description: 自定义remember-me成功处理类 + */ + +@Component +public class RememberMeAuthenticationSuccessHandler implements AuthenticationSuccessHandler { + + @Resource + private LoggingService loggingService; + + @Resource + private ISysUserService sysUserService; + + @Resource + private SessionRegistry sessionRegistry; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + // 记录日志 + Logging logging = new Logging(); + logging.setId(SequenceUtil.makeStringId()); + logging.setTitle("Remember Me"); + logging.setDescription("登录成功"); + logging.setBusinessType(BusinessType.OTHER); + logging.setSuccess(true); + logging.setLoggingType(LoggingType.LOGIN); + loggingService.save(logging); + + // 更新用户 + SysUser sysUser = new SysUser(); + // 获取最近登录时间 + LocalDateTime now = LocalDateTime.now(); + sysUser.setUserId(((SysUser) SecurityUtil.currentUser().getPrincipal()).getUserId()); + sysUser.setLastTime(now); + sysUserService.update(sysUser); + + SysUser currentUser = (SysUser) authentication.getPrincipal(); + currentUser.setLastTime(now); + request.getSession().setAttribute("currentUser", currentUser); + + HttpSessionUtil.expiredSession(request, sessionRegistry); + + // 注册新的SessionInformation + sessionRegistry.registerNewSession(request.getSession().getId(), authentication.getPrincipal()); + } +} diff --git a/pear-entrance/src/main/java/com/pearadmin/security/process/SecurityAuthenticationSuccessHandler.java b/pear-entrance/src/main/java/com/pearadmin/security/process/SecurityAuthenticationSuccessHandler.java index 4aad807a3172a3e8341f0761a96cc2f4b3d6c04b..dfbeb31767e56945b024bcea22354ec82dfcfa6e 100644 --- a/pear-entrance/src/main/java/com/pearadmin/security/process/SecurityAuthenticationSuccessHandler.java +++ b/pear-entrance/src/main/java/com/pearadmin/security/process/SecurityAuthenticationSuccessHandler.java @@ -9,11 +9,14 @@ import com.pearadmin.common.tools.security.SecurityUtil; import com.pearadmin.common.tools.sequence.SequenceUtil; import com.pearadmin.common.tools.servlet.ServletUtil; import com.pearadmin.common.web.domain.response.Result; +import com.pearadmin.security.session.HttpSessionUtil; import com.pearadmin.system.domain.SysUser; import com.pearadmin.system.service.ISysUserService; import org.springframework.security.core.Authentication; +import org.springframework.security.core.session.SessionRegistry; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.stereotype.Component; + import javax.annotation.Resource; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -25,7 +28,7 @@ import java.time.LocalDateTime; * Describe: 自定义 Security 用户未登陆处理类 * Author: 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Component public class SecurityAuthenticationSuccessHandler implements AuthenticationSuccessHandler { @@ -35,8 +38,11 @@ public class SecurityAuthenticationSuccessHandler implements AuthenticationSucce @Resource private ISysUserService sysUserService; + @Resource + private SessionRegistry sessionRegistry; + @Override - public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { // 记录日志 Logging logging = new Logging(); @@ -50,13 +56,20 @@ public class SecurityAuthenticationSuccessHandler implements AuthenticationSucce // 更新用户 SysUser sysUser = new SysUser(); - sysUser.setUserId(((SysUser)SecurityUtil.currentUser().getPrincipal()).getUserId()); - sysUser.setLastTime(LocalDateTime.now()); + // 获取最近登录时间 + LocalDateTime now = LocalDateTime.now(); + sysUser.setUserId(((SysUser) SecurityUtil.currentUser().getPrincipal()).getUserId()); + sysUser.setLastTime(now); sysUserService.update(sysUser); + SysUser currentUser = (SysUser) authentication.getPrincipal(); + currentUser.setLastTime(now); + request.getSession().setAttribute("currentUser", authentication.getPrincipal()); + + HttpSessionUtil.expiredSession(request, sessionRegistry); + // 响应消息 - Result result = Result.success(200,"登录成功"); - httpServletRequest.getSession().setAttribute("currentUser",authentication.getPrincipal()); + Result result = Result.success(200, "登录成功"); ServletUtil.write(JSON.toJSONString(result)); } } 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 new file mode 100644 index 0000000000000000000000000000000000000000..48499610a69ce82883634a55a53199a0c891e8c7 --- /dev/null +++ b/pear-entrance/src/main/java/com/pearadmin/security/process/SecurityLogoutHandler.java @@ -0,0 +1,76 @@ +package com.pearadmin.security.process; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.logout.LogoutHandler; +import org.springframework.security.web.session.HttpSessionEventPublisher; +import org.springframework.util.Assert; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpSessionEvent; + +/** + * @Author: Heiky + * @Date: 2020/12/17 10:33 + * @Description: 自定义用户注销处理类 + */ +public class SecurityLogoutHandler implements LogoutHandler { + + private static final Logger log = LoggerFactory.getLogger(SecurityLogoutHandler.class); + + + private boolean invalidateHttpSession = true; + + private boolean clearAuthentication = true; + + private HttpSessionEventPublisher httpSessionEventPublisher; + + public SecurityLogoutHandler() { + } + + public SecurityLogoutHandler(HttpSessionEventPublisher httpSessionEventPublisher) { + this.httpSessionEventPublisher = httpSessionEventPublisher; + } + + @Override + public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { + Assert.notNull(request, "HttpServletRequest required"); + if (httpSessionEventPublisher != null) { + // 构建要销毁的session + HttpSessionEvent sessionEvent = new HttpSessionEvent(request.getSession()); + httpSessionEventPublisher.sessionDestroyed(sessionEvent); + } + if (invalidateHttpSession) { + HttpSession session = request.getSession(false); + if (session != null) { + log.debug("Invalidating session: " + session.getId()); + session.invalidate(); + } + } + + if (clearAuthentication) { + SecurityContext context = SecurityContextHolder.getContext(); + context.setAuthentication(null); + } + SecurityContextHolder.clearContext(); + } + + public boolean isInvalidateHttpSession() { + return invalidateHttpSession; + } + + public void setInvalidateHttpSession(boolean invalidateHttpSession) { + this.invalidateHttpSession = invalidateHttpSession; + } + + public void setClearAuthentication(boolean clearAuthentication) { + this.clearAuthentication = clearAuthentication; + } + + +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..7a6ea8b2e2969d26fc850970eeb15fb49f0dfe0d --- /dev/null +++ b/pear-entrance/src/main/java/com/pearadmin/security/session/HttpSessionUtil.java @@ -0,0 +1,45 @@ +package com.pearadmin.security.session; + +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 java.util.List; + +/** + * @Author: Heiky + * @Date: 2020/12/17 11:40 + * @Description: + */ +public class HttpSessionUtil { + + /** + * 从sessionRegistry中清除session信息 + * + * @param request + * @param sessionRegistry + */ + public static void expiredSession(HttpServletRequest request, SessionRegistry sessionRegistry) { + SysUser currentUser = (SysUser) request.getSession().getAttribute("currentUser"); + String sessionId = request.getSession().getId(); + List principals = sessionRegistry.getAllPrincipals(); + for (Object principal : principals) { + SysUser userDetails = (SysUser) principal; + if (userDetails != null && userDetails.getUsername().equals(currentUser.getUsername())) { + List sessionInformationList = sessionRegistry.getAllSessions(userDetails, true); + if (CollectionUtil.isNotEmpty(sessionInformationList)) { + for (SessionInformation sessionInformation : sessionInformationList) { + if (sessionId.equals(sessionInformation.getSessionId())) { + continue; + } + sessionInformation.expireNow(); + sessionRegistry.removeSessionInformation(sessionInformation.getSessionId()); + } + } + } + } + } + +} diff --git a/pear-modules/pear-system/src/main/java/com/pearadmin/system/domain/SysUser.java b/pear-modules/pear-system/src/main/java/com/pearadmin/system/domain/SysUser.java index 3e56a98af93a73135c97092fa4fbc45cc0d4f5c1..2f0ce5bae94712f8805c52f849131c5ca2eccb12 100644 --- a/pear-modules/pear-system/src/main/java/com/pearadmin/system/domain/SysUser.java +++ b/pear-modules/pear-system/src/main/java/com/pearadmin/system/domain/SysUser.java @@ -1,7 +1,8 @@ package com.pearadmin.system.domain; import com.pearadmin.common.web.base.BaseDomain; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; import org.apache.ibatis.type.Alias; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; @@ -14,93 +15,92 @@ import java.util.List; * Describe: 用户领域模型 * Author: 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ -@Data + */ + +@Getter +@Setter @Alias("SysUser") public class SysUser extends BaseDomain implements UserDetails { /** * 编号 - * */ + */ private String userId; /** * 账户 - * */ + */ private String username; /** * 密码 - * */ + */ private String password; /** * 盐 - * */ + */ private String salt; /** * 状态 - * */ + */ private String status; /** * 姓名 - * */ + */ private String realName; /** * 邮箱 - * */ + */ private String email; /** * 头像 - * */ + */ private String avatar; /** * 性别 - * */ + */ private String sex; /** * 电话 - * */ + */ private String phone; /** * 所属部门 - * */ + */ private String deptId; /** * 是否启用 - * */ + */ private String enable; /** * 是否登录 - * */ + */ private String login; /** * 计算列 - * */ + */ private String roleIds; /** * 最后一次登录时间 - * - * */ + */ private LocalDateTime lastTime; /** - * * 权限 这里暂时不用 security 的 Authorities - * */ private List powerList; @@ -116,7 +116,7 @@ public class SysUser extends BaseDomain implements UserDetails { @Override public boolean isAccountNonLocked() { - return "1".equals(this.getStatus())?true:false; + return "1".equals(this.getStatus()) ? true : false; } @Override @@ -126,7 +126,7 @@ public class SysUser extends BaseDomain implements UserDetails { @Override public boolean isEnabled() { - return "1".equals(this.getEnable())?true:false; + return "1".equals(this.getEnable()) ? true : false; } }