diff --git a/pom.xml b/pom.xml index 1911d32..b34ddf2 100644 --- a/pom.xml +++ b/pom.xml @@ -127,6 +127,11 @@ qiaoba-module-file ${qiaoba.version} + + com.qiaoba + qiaoba-module-monitor + ${qiaoba.version} + com.qiaoba qiaoba-common-base @@ -157,6 +162,11 @@ qiaoba-common-poi ${qiaoba.version} + + com.qiaoba + qiaoba-api-auth + ${qiaoba.version} + com.qiaoba qiaoba-common-redis diff --git a/qiaoba-apis/pom.xml b/qiaoba-apis/pom.xml index d4424d3..cf81d10 100644 --- a/qiaoba-apis/pom.xml +++ b/qiaoba-apis/pom.xml @@ -15,6 +15,7 @@ qiaoba-api-system qiaoba-api-job qiaoba-api-file + qiaoba-api-auth diff --git a/qiaoba-apis/qiaoba-api-auth/pom.xml b/qiaoba-apis/qiaoba-api-auth/pom.xml new file mode 100644 index 0000000..75f1c2f --- /dev/null +++ b/qiaoba-apis/qiaoba-api-auth/pom.xml @@ -0,0 +1,21 @@ + + + + qiaoba-apis + com.qiaoba + 1.0 + + 4.0.0 + + qiaoba-api-auth + + + + + org.springframework.boot + spring-boot-starter-security + + + \ No newline at end of file diff --git a/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/service/SysUserDetailsApiService.java b/qiaoba-apis/qiaoba-api-auth/src/main/java/com/qiaoba/api/auth/service/SysUserDetailsApiService.java similarity index 56% rename from qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/service/SysUserDetailsApiService.java rename to qiaoba-apis/qiaoba-api-auth/src/main/java/com/qiaoba/api/auth/service/SysUserDetailsApiService.java index 08bacb2..c08d004 100644 --- a/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/service/SysUserDetailsApiService.java +++ b/qiaoba-apis/qiaoba-api-auth/src/main/java/com/qiaoba/api/auth/service/SysUserDetailsApiService.java @@ -1,9 +1,10 @@ -package com.qiaoba.api.system.service; +package com.qiaoba.api.auth.service; import org.springframework.security.core.userdetails.UserDetails; /** * SysUserDetails 暴露接口 + * * @author ailanyin * @version 1.0 * @since 2023/5/19 17:17 @@ -16,5 +17,13 @@ public interface SysUserDetailsApiService { * @param username username * @return UserDetails */ - UserDetails toCache(String username); + UserDetails toCache(String username, String deviceSn); + + /** + * 从缓存中删除 + * + * @param username username + * @param deviceSn deviceSn + */ + void deleteCache(String username, String deviceSn); } diff --git a/qiaoba-apis/qiaoba-api-system/pom.xml b/qiaoba-apis/qiaoba-api-system/pom.xml index f806e7c..b3bbcd0 100644 --- a/qiaoba-apis/qiaoba-api-system/pom.xml +++ b/qiaoba-apis/qiaoba-api-system/pom.xml @@ -24,10 +24,6 @@ jakarta.validation jakarta.validation-api - - com.qiaoba - qiaoba-auth - com.qiaoba qiaoba-common-poi diff --git a/qiaoba-application/pom.xml b/qiaoba-application/pom.xml index eb5244e..5d664dc 100644 --- a/qiaoba-application/pom.xml +++ b/qiaoba-application/pom.xml @@ -12,6 +12,10 @@ qiaoba-application + + com.qiaoba + qiaoba-module-monitor + com.qiaoba qiaoba-module-system diff --git a/qiaoba-application/src/main/resources/application-dev.yml b/qiaoba-application/src/main/resources/application-dev.yml index 3db976d..1925b39 100644 --- a/qiaoba-application/src/main/resources/application-dev.yml +++ b/qiaoba-application/src/main/resources/application-dev.yml @@ -3,9 +3,9 @@ qiaoba: datasource: master: driver: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://localhost:3306/qiaoba-boot?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true + url: jdbc:mysql://120.79.217.22:3306/qiaoba-boot?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true username: root - password: root + password: FeyZ7xZr6JtuKibm pool: init: 5 #连接池初始化大小 min: 10 #最小空闲连接数 diff --git a/qiaoba-auth/pom.xml b/qiaoba-auth/pom.xml index 2a2c23f..40bda60 100644 --- a/qiaoba-auth/pom.xml +++ b/qiaoba-auth/pom.xml @@ -12,10 +12,9 @@ qiaoba-auth - - org.springframework.boot - spring-boot-starter-security + com.qiaoba + qiaoba-api-auth diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/LoginUser.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/LoginUser.java index 6e7c8a0..f07a0f0 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/LoginUser.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/LoginUser.java @@ -64,7 +64,8 @@ public class LoginUser implements UserDetails { public LoginUser() { } - public LoginUser(String userId, String deptId, String username, String nickname, List roles, List roleKeys, Set permissions) { + public LoginUser(String deviceSn, String userId, String deptId, String username, String nickname, List roles, List roleKeys, Set permissions) { + this.deviceSn = deviceSn; this.userId = userId; this.deptId = deptId; this.username = username; diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/OnlineUser.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/OnlineUser.java index f5f8286..c9e726b 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/OnlineUser.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/OnlineUser.java @@ -1,6 +1,8 @@ package com.qiaoba.auth.entity; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import java.io.Serializable; import java.util.Date; @@ -13,6 +15,8 @@ import java.util.Date; * @since 2023/5/25 17:05 */ @Data +@AllArgsConstructor +@NoArgsConstructor public class OnlineUser implements Serializable { private static final long serialVersionUID = 1L; diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/SecurityUser.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/SecurityUser.java index da9c8f6..645f3b7 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/SecurityUser.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/SecurityUser.java @@ -26,6 +26,11 @@ public class SecurityUser implements Serializable { */ private String userId; + /** + * 设备SN + */ + private String deviceSn; + /** * 部门ID */ diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/JwtAuthenticationTokenFilter.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/JwtAuthenticationTokenFilter.java index 8d4fd22..73828e5 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/JwtAuthenticationTokenFilter.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/JwtAuthenticationTokenFilter.java @@ -6,6 +6,7 @@ import com.qiaoba.auth.entity.OnlineUser; import com.qiaoba.auth.properties.AuthConfigProperties; import com.qiaoba.auth.service.OnlineUserService; import com.qiaoba.auth.utils.TokenUtil; +import com.qiaoba.common.redis.service.RedisService; import com.qiaoba.common.web.utils.ResponseUtil; import lombok.RequiredArgsConstructor; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -33,6 +34,7 @@ import java.util.Objects; @RequiredArgsConstructor public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { + private final RedisService redisService; private final UserDetailsService userDetailsService; private final OnlineUserService onlineUserService; private final AuthConfigProperties authConfigProperties; @@ -51,24 +53,28 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { String authHeader = request.getHeader(SecurityConstant.TOKEN_HEADER); if (StrUtil.isNotBlank(authHeader) && authHeader.startsWith(SecurityConstant.TOKEN_HEAD)) { String authToken = authHeader.substring(SecurityConstant.TOKEN_HEAD.length()); - // todo -/* String username1 = "admin"; - OnlineUser onlineUser = onlineUserService.selectByUsername(username1); - if (Objects.isNull(onlineUser)) { - ResponseUtil.errorAuth(response, 4011, "暂无登录"); - return; - }*/ - // 续期有效期 - //onlineUserService.insert(onlineUser); - if (TokenUtil.validateToken(authToken)) { - String username = TokenUtil.getUserNameFromToken(authToken); - if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { - UserDetails userDetails = userDetailsService.loadUserByUsername(username); - UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); - authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); - SecurityContextHolder.getContext().setAuthentication(authentication); + String username = authToken.split(":")[0]; + String deviceSn = authToken.split(":")[1]; + + if (!"/logout".equals(request.getRequestURI())) { + if (redisService.hasKey(SecurityConstant.LOGGED_USER_REDIS_KEY + username)) { + if (!onlineUserService.checkIsLastLogged(username, deviceSn)) { + ResponseUtil.errorAuth(response, 4012, "被挤下线"); + onlineUserService.deleteOne(username, deviceSn); + return; + } + } else { + ResponseUtil.errorAuth(response, 4011, "登陆过期"); + return; } } + + if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { + UserDetails userDetails = userDetailsService.loadUserByUsername(username); + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authentication); + } } chain.doFilter(request, response); diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/handler/LogoutHandler.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/handler/LogoutHandler.java index 465901b..38ca355 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/handler/LogoutHandler.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/handler/LogoutHandler.java @@ -1,6 +1,5 @@ package com.qiaoba.auth.handler; -import com.qiaoba.auth.constants.SecurityConstant; import com.qiaoba.auth.entity.LoginUser; import com.qiaoba.auth.service.OnlineUserService; import com.qiaoba.common.redis.service.RedisService; @@ -32,7 +31,6 @@ public class LogoutHandler implements LogoutSuccessHandler { public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { // 删除缓存中的用户信息 LoginUser user = (LoginUser) authentication.getPrincipal(); - redisService.del(SecurityConstant.USER_DETAILS_REDIS_KEY + user.getUsername()); onlineUserService.deleteOne(user.getUsername(), user.getDeviceSn()); } } diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/service/OnlineUserService.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/service/OnlineUserService.java index e88ea8a..2a9e9b8 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/service/OnlineUserService.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/service/OnlineUserService.java @@ -52,5 +52,12 @@ public interface OnlineUserService { */ List selectList(String username); - + /** + * 检查设备是否是最新登陆的设备 + * + * @param username username + * @param deviceSn deviceSn + * @return 结果 + */ + Boolean checkIsLastLogged(String username, String deviceSn); } diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/service/impl/OnlineUserServiceImpl.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/service/impl/OnlineUserServiceImpl.java index 79a4d4e..a2f484a 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/service/impl/OnlineUserServiceImpl.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/service/impl/OnlineUserServiceImpl.java @@ -1,15 +1,18 @@ package com.qiaoba.auth.service.impl; import cn.hutool.core.util.StrUtil; +import com.qiaoba.api.auth.service.SysUserDetailsApiService; import com.qiaoba.auth.constants.SecurityConstant; import com.qiaoba.auth.entity.OnlineUser; import com.qiaoba.auth.service.OnlineUserService; import com.qiaoba.auth.utils.TokenUtil; +import com.qiaoba.common.base.constants.BaseConstant; import com.qiaoba.common.redis.service.RedisService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import java.util.Collections; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; /** @@ -24,29 +27,34 @@ import java.util.List; public class OnlineUserServiceImpl implements OnlineUserService { private final RedisService redisService; + private final SysUserDetailsApiService sysUserDetailsApiService; @Override public void insert(OnlineUser onlineUser) { - // key: username - // hashKey: deviceSn + // key: username:deviceSn // value: onlineUser - redisService.hSet(handleKey(onlineUser.getUsername()), onlineUser.getDeviceSn(), onlineUser, TokenUtil.expireTime * 3600); + redisService.set(handleKey(onlineUser.getUsername(), onlineUser.getDeviceSn()), onlineUser, TokenUtil.expireTime * 3600); } @Override public void deleteOne(String username, String deviceSn) { - redisService.hDel(handleKey(username), deviceSn); + if (deviceSn.equals(redisService.get(SecurityConstant.LOGGED_USER_REDIS_KEY + username))) { + redisService.del(SecurityConstant.LOGGED_USER_REDIS_KEY + username); + } + sysUserDetailsApiService.deleteCache(username, deviceSn); + redisService.del(handleKey(username, deviceSn)); } @Override public void deleteAll(String username) { - redisService.del(handleKey(username)); + } @Override public OnlineUser selectOne(String username, String deviceSn) { - if (redisService.hHasKey(username, deviceSn)) { - return redisService.hGetObject(username, deviceSn, OnlineUser.class); + String key = handleKey(username, deviceSn); + if (redisService.hasKey(key)) { + return redisService.getObject(key, OnlineUser.class); } return null; } @@ -58,13 +66,22 @@ public class OnlineUserServiceImpl implements OnlineUserService { key = key + username + "*"; } - if (redisService.hasKey(key)) { - return redisService.getObjectList(key, OnlineUser.class); + List users = new ArrayList<>(); + Collection keys = redisService.getKeys(key); + for (String temp : keys) { + temp = temp.replace("tenant_1:", ""); + users.add(redisService.getObject(temp, OnlineUser.class)); } - return Collections.emptyList(); + return users; } - private String handleKey(String key) { - return SecurityConstant.ONLINE_USER_REDIS_KEY + key; + @Override + public Boolean checkIsLastLogged(String username, String deviceSn) { + String loggedDevice = redisService.get(SecurityConstant.LOGGED_USER_REDIS_KEY + username).toString(); + return deviceSn.equals(loggedDevice); + } + + private String handleKey(String key, String deviceSn) { + return SecurityConstant.ONLINE_USER_REDIS_KEY + key + BaseConstant.COLON_JOIN_STR + deviceSn; } } diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/utils/TokenUtil.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/utils/TokenUtil.java index d2b0bea..1e8d679 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/utils/TokenUtil.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/utils/TokenUtil.java @@ -22,7 +22,7 @@ public class TokenUtil { * jwt 加解密密钥,第一次项目启动时创建随机数 */ public static String secret; - public static Integer expireTime = 1; + public static Integer expireTime = 72; public static String generateToken(String username) { DateTime now = DateTime.now(); diff --git a/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/BaseConstant.java b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/BaseConstant.java index 18f1eeb..7081af7 100644 --- a/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/BaseConstant.java +++ b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/BaseConstant.java @@ -24,6 +24,11 @@ public class BaseConstant { */ public static final String LINE_JOIN_STR = "|"; + /** + * 冒号拼接符号: ':'(英文冒号) + */ + public static final String COLON_JOIN_STR = ":"; + /** * 树的key的命名 */ diff --git a/qiaoba-modules/pom.xml b/qiaoba-modules/pom.xml index c8bf244..df05ea5 100644 --- a/qiaoba-modules/pom.xml +++ b/qiaoba-modules/pom.xml @@ -15,6 +15,7 @@ qiaoba-module-system qiaoba-module-job qiaoba-module-file + qiaoba-module-monitor diff --git a/qiaoba-modules/qiaoba-module-monitor/pom.xml b/qiaoba-modules/qiaoba-module-monitor/pom.xml new file mode 100644 index 0000000..33e07f0 --- /dev/null +++ b/qiaoba-modules/qiaoba-module-monitor/pom.xml @@ -0,0 +1,28 @@ + + + + qiaoba-modules + com.qiaoba + 1.0 + + 4.0.0 + + qiaoba-module-monitor + + + + com.qiaoba + qiaoba-auth + + + com.qiaoba + qiaoba-common-doc + + + com.qiaoba + qiaoba-common-datasource + + + \ No newline at end of file diff --git a/qiaoba-modules/qiaoba-module-monitor/src/main/java/com/qiaoba/module/monitor/controller/OnlineUserController.java b/qiaoba-modules/qiaoba-module-monitor/src/main/java/com/qiaoba/module/monitor/controller/OnlineUserController.java new file mode 100644 index 0000000..959110f --- /dev/null +++ b/qiaoba-modules/qiaoba-module-monitor/src/main/java/com/qiaoba/module/monitor/controller/OnlineUserController.java @@ -0,0 +1,41 @@ +package com.qiaoba.module.monitor.controller; + +import com.qiaoba.auth.service.OnlineUserService; +import com.qiaoba.common.base.result.AjaxResult; +import com.qiaoba.common.database.entity.TableDataInfo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +/** + * 在线用户管理 Web层 + * + * @author ailanyin + * @version 1.0 + * @since 2023-05-27 21:59:12 + */ +@RestController +@RequestMapping("/monitor/online") +@RequiredArgsConstructor +@Tag(name = "在线用户管理") +public class OnlineUserController { + + private final OnlineUserService onlineUserService; + + @PreAuthorize("hasAuthority('monitor:online:list')") + @Operation(summary = "获取列表") + @GetMapping("/list") + public TableDataInfo getList(String username) { + return TableDataInfo.build(onlineUserService.selectList(username)); + } + + @PreAuthorize("hasAuthority('monitor:online:forceLogout')") + @DeleteMapping("/{username}/{deviceSn}") + @Operation(summary = "强退用户") + public AjaxResult forceLogout(@PathVariable String username, @PathVariable String deviceSn) { + onlineUserService.deleteOne(username, deviceSn); + return AjaxResult.success(); + } +} diff --git a/qiaoba-modules/qiaoba-module-system/pom.xml b/qiaoba-modules/qiaoba-module-system/pom.xml index d8daecc..a8ddd91 100644 --- a/qiaoba-modules/qiaoba-module-system/pom.xml +++ b/qiaoba-modules/qiaoba-module-system/pom.xml @@ -16,6 +16,10 @@ com.qiaoba qiaoba-api-system + + com.qiaoba + qiaoba-api-auth + com.qiaoba qiaoba-api-file diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysLoginServiceImpl.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysLoginServiceImpl.java index 95a48ea..03014ab 100644 --- a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysLoginServiceImpl.java +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysLoginServiceImpl.java @@ -6,10 +6,14 @@ import cn.hutool.core.lang.UUID; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.http.useragent.UserAgent; +import cn.hutool.http.useragent.UserAgentUtil; import com.qiaoba.api.system.entity.SysUser; import com.qiaoba.api.system.entity.dto.LoginDto; -import com.qiaoba.api.system.service.SysUserDetailsApiService; +import com.qiaoba.api.auth.service.SysUserDetailsApiService; import com.qiaoba.auth.constants.SecurityConstant; +import com.qiaoba.auth.entity.OnlineUser; +import com.qiaoba.auth.service.OnlineUserService; import com.qiaoba.auth.utils.SecurityUtil; import com.qiaoba.auth.utils.TokenUtil; import com.qiaoba.common.base.enums.BaseEnum; @@ -22,6 +26,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; +import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -40,6 +45,7 @@ public class SysLoginServiceImpl implements SysLoginService { private final HttpServletRequest request; private final SysUserDetailsApiService userDetailsService; private final SysUserService sysUserService; + private final OnlineUserService onlineUserService; @Override public Map getCaptchaImage() { @@ -70,10 +76,12 @@ public class SysLoginServiceImpl implements SysLoginService { validateUser(dto.getUsername(), sysUser); // 检验密码 validatePassword(dto.getUsername(), sysUser.getPassword(), dto.getPassword()); - // 缓存user - userDetailsService.toCache(sysUser.getUsername()); + // 缓存在线用户 + String deviceSn = cacheOnlineUser(dto.getUsername(), sysUser.getNickname()); + // 缓存userDetails + userDetailsService.toCache(sysUser.getUsername(), deviceSn); // 生成Token - return TokenUtil.generateToken(sysUser.getUsername()); + return dto.getUsername() + ":" + deviceSn; } private void validatePassword(String username, String password, String inputPassword) { @@ -131,4 +139,17 @@ public class SysLoginServiceImpl implements SysLoginService { } } } + + private String cacheOnlineUser(String username, String nickname) { + String deviceSn = UUID.fastUUID().toString(true); + String ip = IpUtil.getIp(request); + String address = IpUtil.getIpAddr(ip); + UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent")); + String browser = userAgent.getBrowser().getName() + userAgent.getVersion(); + String os = userAgent.getOs().getName(); + + redisService.set(SecurityConstant.LOGGED_USER_REDIS_KEY + username, deviceSn, TokenUtil.expireTime * 3600); + onlineUserService.insert(new OnlineUser(deviceSn, username, nickname, ip, address, browser, os, new Date())); + return deviceSn; + } } diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysUserDetailsServiceImpl.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysUserDetailsServiceImpl.java index 0bd5b84..7beae42 100644 --- a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysUserDetailsServiceImpl.java +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysUserDetailsServiceImpl.java @@ -1,9 +1,8 @@ package com.qiaoba.module.system.service.impl; import cn.hutool.core.bean.BeanUtil; -import cn.hutool.json.JSONUtil; import com.qiaoba.api.system.entity.SysUser; -import com.qiaoba.api.system.service.SysUserDetailsApiService; +import com.qiaoba.api.auth.service.SysUserDetailsApiService; import com.qiaoba.auth.constants.SecurityConstant; import com.qiaoba.auth.entity.LoginUser; import com.qiaoba.auth.entity.SecurityUser; @@ -21,6 +20,7 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -44,26 +44,34 @@ public class SysUserDetailsServiceImpl implements UserDetailsService, SysUserDet public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { if (redisService.hasKey(SecurityConstant.USER_DETAILS_REDIS_KEY + username)) { SecurityUser user = redisService.getObject(SecurityConstant.USER_DETAILS_REDIS_KEY + username, SecurityUser.class); - return new LoginUser(user.getUserId(), user.getDeptId(), user.getUsername(), user.getNickname(), user.getRoles(), user.getRoleKeys(), user.getPermissions()); + return new LoginUser(user.getDeviceSn(), user.getUserId(), user.getDeptId(), user.getUsername(), user.getNickname(), user.getRoles(), user.getRoleKeys(), user.getPermissions()); } - return toCache(username); + return null; } - private UserDetails createUserDetails(SysUser user) { + private UserDetails createUserDetails(SysUser user, String deviceSn) { Set perms = sysMenuService.selectPermsByUserId(user.getUserId()); List roles = sysUserRoleService.selectRoleDtoByUserId(user.getUserId(), BaseEnum.NORMAL.getCode()); List roleKeys = roles.stream().map(RoleDto::getRoleKey).collect(Collectors.toList()); - return new LoginUser(user.getUserId(), user.getDeptId(), user.getUsername(), user.getNickname(), roles, roleKeys, perms); + return new LoginUser(deviceSn, user.getUserId(), user.getDeptId(), user.getUsername(), user.getNickname(), roles, roleKeys, perms); } @Override - public UserDetails toCache(String username) { + public UserDetails toCache(String username, String deviceSn) { SysUser user = sysUserService.selectByUsername(username); - UserDetails details = createUserDetails(user); + UserDetails details = createUserDetails(user, deviceSn); SecurityUser securityUser = BeanUtil.copyProperties(details, SecurityUser.class); redisService.set(SecurityConstant.USER_DETAILS_REDIS_KEY + username, securityUser, TokenUtil.expireTime * 3600); return details; } + + @Override + public void deleteCache(String username, String deviceSn) { + SecurityUser user = redisService.getObject(SecurityConstant.USER_DETAILS_REDIS_KEY + username, SecurityUser.class); + if (Objects.nonNull(user) && deviceSn.equals(user.getDeviceSn())) { + redisService.del(SecurityConstant.USER_DETAILS_REDIS_KEY + username); + } + } }