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);
+ }
+ }
}