From 8aad406ab02d9faf65207d17dc6d7572692b8506 Mon Sep 17 00:00:00 2001 From: ailanyin Date: Fri, 7 Jul 2023 12:52:16 +0800 Subject: [PATCH] add --- .../api/auth/constants/SecurityConstant.java | 3 +- .../qiaoba/api/auth/entity/SecurityUser.java | 5 --- .../service/SysUserDetailsApiService.java | 7 ---- .../qiaoba/auth/filters/OnlineUserFilter.java | 16 ++++----- .../service/impl/OnlineUserServiceImpl.java | 35 ++++++++++++++----- .../common/redis/service/RedisService.java | 8 +++++ .../redis/service/impl/RedisServiceImpl.java | 5 +++ .../service/impl/SysLoginServiceImpl.java | 9 ++--- .../impl/SysUserDetailsServiceImpl.java | 10 ++---- 9 files changed, 57 insertions(+), 41 deletions(-) diff --git a/qiaoba-apis/qiaoba-api-auth/src/main/java/com/qiaoba/api/auth/constants/SecurityConstant.java b/qiaoba-apis/qiaoba-api-auth/src/main/java/com/qiaoba/api/auth/constants/SecurityConstant.java index 8962609..943cf1b 100644 --- a/qiaoba-apis/qiaoba-api-auth/src/main/java/com/qiaoba/api/auth/constants/SecurityConstant.java +++ b/qiaoba-apis/qiaoba-api-auth/src/main/java/com/qiaoba/api/auth/constants/SecurityConstant.java @@ -21,7 +21,8 @@ public class SecurityConstant { public static final String REDIS_SECRET_KEY = "sys:secret:secret"; public static final String USER_DETAILS_REDIS_KEY = "user_details:"; public static final String ONLINE_USER_REDIS_KEY = "online_user:"; - public static final String LOGGED_USER_REDIS_KEY = "logged_user:"; + public static final String LAST_LOGIN_USER_REDIS_KEY = "last_login_user:"; + public static final String LOGIN_USER_DEVICES_REDIS_KEY = "login_user_devices:"; /** diff --git a/qiaoba-apis/qiaoba-api-auth/src/main/java/com/qiaoba/api/auth/entity/SecurityUser.java b/qiaoba-apis/qiaoba-api-auth/src/main/java/com/qiaoba/api/auth/entity/SecurityUser.java index 8aac815..81ad68c 100644 --- a/qiaoba-apis/qiaoba-api-auth/src/main/java/com/qiaoba/api/auth/entity/SecurityUser.java +++ b/qiaoba-apis/qiaoba-api-auth/src/main/java/com/qiaoba/api/auth/entity/SecurityUser.java @@ -26,11 +26,6 @@ public class SecurityUser implements Serializable { */ private String userId; - /** - * 设备SN - */ - private String deviceSn; - /** * 部门ID */ diff --git a/qiaoba-apis/qiaoba-api-auth/src/main/java/com/qiaoba/api/auth/service/SysUserDetailsApiService.java b/qiaoba-apis/qiaoba-api-auth/src/main/java/com/qiaoba/api/auth/service/SysUserDetailsApiService.java index 1314f64..f1341ad 100644 --- a/qiaoba-apis/qiaoba-api-auth/src/main/java/com/qiaoba/api/auth/service/SysUserDetailsApiService.java +++ b/qiaoba-apis/qiaoba-api-auth/src/main/java/com/qiaoba/api/auth/service/SysUserDetailsApiService.java @@ -20,11 +20,4 @@ public interface SysUserDetailsApiService { */ UserDetails toCache(String username, String deviceSn); - /** - * 从缓存中删除 - * - * @param username username - * @param deviceSn deviceSn - */ - void deleteCache(String username, String deviceSn); } diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/OnlineUserFilter.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/OnlineUserFilter.java index 9965a1e..a3dc3f4 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/OnlineUserFilter.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/OnlineUserFilter.java @@ -60,9 +60,15 @@ public class OnlineUserFilter extends OncePerRequestFilter { String deviceSn = onlineUserDto.getDeviceSn(); UserDetails userDetails = userDetailsService.loadUserByUsername(username); + if (Objects.isNull(userDetails)) { + onlineUserService.deleteOne(username, deviceSn, true); + ResponseUtil.errorAuth(response, 4011, "登陆过期"); + return; + } + // 不允许同时在线 if (!authConfigApiService.checkAllowBothOnline()) { - if (redisService.hasKey(SecurityConstant.LOGGED_USER_REDIS_KEY + username)) { + if (redisService.hasKey(SecurityConstant.LAST_LOGIN_USER_REDIS_KEY + username)) { if (!onlineUserService.checkIsLastLogged(username, deviceSn)) { onlineUserService.deleteOne(username, deviceSn, true); ResponseUtil.errorAuth(response, 4012, "被挤下线"); @@ -72,13 +78,7 @@ public class OnlineUserFilter extends OncePerRequestFilter { ResponseUtil.errorAuth(response, 4011, "登陆过期"); return; } - } - // 允许同时在线 - else { - if (Objects.isNull(userDetails)) { - ResponseUtil.errorAuth(response, 4011, "登陆过期"); - return; - } + } chain.doFilter(request, response); 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 6f85046..1b1d7c3 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 @@ -2,10 +2,10 @@ package com.qiaoba.auth.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; -import com.qiaoba.api.auth.service.SysUserDetailsApiService; import com.qiaoba.api.auth.constants.SecurityConstant; import com.qiaoba.api.auth.entity.OnlineUser; import com.qiaoba.api.auth.entity.dto.OnlineUserDto; +import com.qiaoba.api.auth.service.AuthConfigApiService; import com.qiaoba.api.auth.service.OnlineUserService; import com.qiaoba.api.auth.utils.TokenUtil; import com.qiaoba.common.base.constants.BaseConstant; @@ -32,9 +32,8 @@ import java.util.List; public class OnlineUserServiceImpl implements OnlineUserService { private final RedisService redisService; - private final SysUserDetailsApiService sysUserDetailsApiService; private final HttpServletRequest request; - + private final AuthConfigApiService authConfigApiService; @Override public void insert(OnlineUser onlineUser) { @@ -48,11 +47,31 @@ public class OnlineUserServiceImpl implements OnlineUserService { throw new ServiceException("禁止踢出自己!"); } - 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)); + + // 允许同时在线 + if (authConfigApiService.checkAllowBothOnline()) { + // > 1 说明还有其他设备登录着 不能删除 userDetail || == 1 说明没有其他设备 可以删除 userDetail + if (redisService.hSize(SecurityConstant.LOGIN_USER_DEVICES_REDIS_KEY + username) <= 1) { + // 删除 userDetail + redisService.del(SecurityConstant.USER_DETAILS_REDIS_KEY + username); + } + } + // 不允许同时在线 + else { + // 最后登录的设备是自己 可以删除 userDetail + if (checkIsLastLogged(username, deviceSn)) { + redisService.del(SecurityConstant.USER_DETAILS_REDIS_KEY + username); + } + } + + // 删除最后登录的用户设备 + if (deviceSn.equals(redisService.get(SecurityConstant.LAST_LOGIN_USER_REDIS_KEY + username))) { + redisService.del(SecurityConstant.LAST_LOGIN_USER_REDIS_KEY + username); + } + // 删除 hash中的自己 + redisService.hDel(SecurityConstant.LOGIN_USER_DEVICES_REDIS_KEY + username, deviceSn); } @Override @@ -82,7 +101,7 @@ public class OnlineUserServiceImpl implements OnlineUserService { @Override public Boolean checkIsLastLogged(String username, String deviceSn) { - String loggedDevice = redisService.get(SecurityConstant.LOGGED_USER_REDIS_KEY + username).toString(); + String loggedDevice = redisService.get(SecurityConstant.LAST_LOGIN_USER_REDIS_KEY + username).toString(); return deviceSn.equals(loggedDevice); } diff --git a/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/RedisService.java b/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/RedisService.java index 3708b6d..aea6804 100644 --- a/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/RedisService.java +++ b/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/RedisService.java @@ -141,6 +141,14 @@ public interface RedisService { */ Map hGetAll(String key); + /** + * 获取整个hash结构的大小 + * + * @param key key + * @return size + */ + Long hSize(String key); + /** * 直接设置整个Hash结构 * diff --git a/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/impl/RedisServiceImpl.java b/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/impl/RedisServiceImpl.java index dbf8f64..3d25d0d 100644 --- a/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/impl/RedisServiceImpl.java +++ b/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/impl/RedisServiceImpl.java @@ -102,6 +102,11 @@ public class RedisServiceImpl implements RedisService { return redisTemplate.opsForHash().entries(addTenantPrefix(key)); } + @Override + public Long hSize(String key) { + return redisTemplate.opsForHash().size(addTenantPrefix(key)); + } + @Override public Boolean hSetAll(String key, Map map, long time) { String newKey = addTenantPrefix(key); 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 00f09b8..1a0ecaf 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 @@ -166,12 +166,13 @@ public class SysLoginServiceImpl implements SysLoginService { UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent")); String browser = userAgent.getBrowser().getName() + BaseConstant.LINE_JOIN_STR + userAgent.getVersion(); String os = userAgent.getOs().getName(); - - if (!authConfigApiService.checkAllowBothOnline()) { - redisService.set(SecurityConstant.LOGGED_USER_REDIS_KEY + username, deviceSn, TokenUtil.TOKEN_EXPIRE_HOUR_TIME * 3600); - } OnlineUser onlineUser = new OnlineUser(deviceSn, username, nickname, ip, address, browser, os, new Date()); onlineUserService.insert(onlineUser); + redisService.set(SecurityConstant.LAST_LOGIN_USER_REDIS_KEY + username, deviceSn, TokenUtil.TOKEN_EXPIRE_HOUR_TIME * 3600); + // 允许同时在线 + if (authConfigApiService.checkAllowBothOnline()) { + redisService.hSet(SecurityConstant.LOGIN_USER_DEVICES_REDIS_KEY + username, deviceSn, 1, TokenUtil.TOKEN_EXPIRE_HOUR_TIME * 3600); + } return onlineUser; } 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 2d98e5f..cc70c3f 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,6 +1,8 @@ package com.qiaoba.module.system.service.impl; import cn.hutool.core.bean.BeanUtil; +import com.qiaoba.api.auth.service.AuthConfigApiService; +import com.qiaoba.api.auth.service.OnlineUserService; import com.qiaoba.api.auth.service.SysUserDetailsApiService; import com.qiaoba.api.system.entity.SysUser; import com.qiaoba.api.auth.constants.SecurityConstant; @@ -59,16 +61,8 @@ public class SysUserDetailsServiceImpl implements UserDetailsService, SysUserDet SysUser user = sysUserService.selectByUsername(username); UserDetails details = createUserDetails(user); SecurityUser securityUser = BeanUtil.copyProperties(details, SecurityUser.class); - securityUser.setDeviceSn(deviceSn); redisService.set(SecurityConstant.USER_DETAILS_REDIS_KEY + username, securityUser, TokenUtil.TOKEN_EXPIRE_HOUR_TIME * 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); - } - } }